Разница между "..." и х "..." в партии - PullRequest
0 голосов
/ 20 сентября 2018

Я недавно нашел этот пост https://stackoverflow.com/a/7006016/4374266, где говорится, что с учетом

@setlocal enableextensions enabledelayedexpansion
@echo off
set str1=%1
if not x%str1:bcd=%==x%str1% echo It contains bcd
endlocal

затем

x перед двумя сторонами равенствачтобы убедиться, что строка bcd работает нормально.Он также защищает от некоторых «неправильных» начальных символов.

Однако я не нашел никакого объяснения фактическому действию этого x.Так в чем же разница между x"%string%" и "%string%"?

(Ссылка на актуальную документацию является верным ответом, так как я не смог ее найти.)

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

Это просто очень плохое сравнение кодированных строк.x с обеих сторон позволяет сравнивать две строки, даже если %str1:bcd=% или %str1% заменены командным процессором Windows при анализе всей командной строки пустой строкой перед выполнением команды IF .

Но выполнение пакетного файла, тем не менее, немедленно прекращается cmd.exe из-за синтаксической ошибки в случае значения переменной среды str1 содержит символ пробела или "&<>|.

Заключение строки аргумента в двойные кавычки приводит к получению всех символов, кроме знака процента, и с включенным расширением отложенной переменной среды, а также восклицательного знака, интерпретируемого как буквенный символ, включая пробел, который находится вне строки в двойных кавычках, интерпретируемой как разделитель строки аргумента.* Намного лучше:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if "%~1" == "" goto EndBatch
set "str1=%~1"
if not "%str1:bcd=%" == "%str1%" echo It contains bcd
:EndBatch
endlocal

Первый аргумент командного файла сравнивается первым без двойных кавычек с пустой строкой.Таким образом, если пакетный файл запускается без какого-либо аргумента или только с "" в качестве строки первого аргумента, командный процессор Windows выполняет команду GOTO , что приводит к восстановлению предыдущей среды, помещенной в стек, с помощью команды SETLOCAL и выходит из пакетного файла.

В противном случае пакетный файл действительно вызывается со строкой аргумента.Эта строка аргумента присваивается переменной окружения str1 с удалением окружающих двойных кавычек, если они есть.Таким образом, при вызове пакетного файла с аргументом test значение test присваивается переменной окружения str1, а при вызове с помощью "another test" значение another test без двойных кавычек присваивается str1.И даже при вызове пакетного файла с неверно закодированной строкой аргумента "bcd test (отсутствует секунда ") только bcd test присваивается переменной окружения str1.

IF условие сравнивает значение переменной среды str1 со всеми удаленными вхождениями bcd со значением неизмененной переменной.Двойные кавычки вокруг двух строк позволяют сравнивать две строки, даже если они содержат пробел или амперсанд или операторы перенаправления <>|.Команда IF включает в себя двойные кавычки при сравнении двух строк.

Итак, теперь этот код безопасен?

Нет, это не тот случай, когда кто-то вызывает пакетнедопустимый файл с test_bcd" в качестве строки аргумента, в которой отсутствует первая двойная кавычка.В этом случае первая IF командная строка, выполняемая cmd.exe:

if "test_bcd"" == "" goto EndBatch

Конечный " неверно указанной строки аргумента не удаляется cmd.exe и вызываетсинтаксическая ошибка в этой командной строке при выполнении, которую можно увидеть при запуске командного файла из окна командной строки с изменением первой строки на @echo on.

Одно из решений без использования отложенного расширения переменной среды:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "str1=%~1"
if not defined str1 goto EndBatch
set "str1=%str1:"=%"
if not defined str1 goto EndBatch
if not "%str1:bcd=%" == "%str1%" echo It contains bcd
:EndBatch
endlocal

Этот код гарантирует, что str1 не содержит никаких двойных кавычек перед выполнением команды IF для сравнения строк.

Другое решение - использование среды с задержкойрасширение переменной:

@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "str1=%~1"
if not "!str1:bcd=!" == "!str1!" echo It contains bcd
endlocal

Это выглядит лучше, как в приведенном выше коде, без использования отложенного расширения переменной среды.Но он не работает должным образом, если строка аргумента, например, "!Hello!", потому что в этом случае условие if not также верно, и поэтому выводом является сообщение It contains bcd, хотя строка !Hello! не содержит bcd*как буквальные символы.Затем включается отложенное расширение для сравнения строк с использованием отложенного расширения переменной среды, что позволяет избежать изменения самой командной строки с помощью cmd.exe перед выполнением команды IF .

Чтобы понять используемые команды и то, как они работают, откройте окно командной строки, выполните там следующие команды и очень внимательно прочитайте все страницы справки, отображаемые для каждой команды.

  • call /?... объясняет %~1, не так хорошо, как здесь.
  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • set /?
  • setlocal /?

См. Также:

0 голосов
/ 20 сентября 2018

Добавление x (или любого другого алфавитного символа) перед строкой гарантирует, что оператор отношения синтаксически допустим, даже если / если строка пуста.

Предположим, str1 - пустая строка.Затем сравнение %str1:bcd=%==%str1% после замены вырождается в ==, что синтаксически неверно.

Однако, с x перед, сравнение становится x==x и может быть оценено.Естественно, добавление одинакового префикса к каждой из двух строк не влияет на их (не) равенство.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...