Почему в параметре "for /F" или "for /R" нет необходимости избегать восклицательных знаков?
, когда отложенная экспансия включено, (обычно) необходимо правильно избегать восклицательных знаков, чтобы получить буквальные (например,^^!
или, находясь между ""
, ^!
, чтобы получить буквальное !
).
/R
или /F
переключатель for
петли команда?
имея в виду вышеупомянутые правила экранирования, я создал следующий пакетный скрипт, используя for /R
и в качестве параметра каталог с !
в его названии (указано после ):
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "TARGET=excl^!dir"
set "FILE=empty_%RANDOM%.txt"
echo/
echo creating directory: !TARGET!
mkdir "!TARGET!"
echo placing empty file: !TARGET!%FILE%
> "!TARGET!%FILE%" break
echo/
echo adequately escaped `^^!`:
for /R "excl^!dir" %%F in ("*.*") do echo(found item: %%~nxF
for /R excl^^!dir %%F in ("*.*") do echo(found item: %%~nxF
echo/
echo improperly escaped `^^!`:
for /R "excl!dir" %%F in ("*.*") do echo(found item: %%~nxF
for /R excl!dir %%F in ("*.*") do echo(found item: %%~nxF
for /R excl^!dir %%F in ("*.*") do echo(found item: %%~nxF
erase "!TARGET!%FILE%"
rmdir "!TARGET!"
endlocal
exit /B
удивительно, каталог перечисляется только без побег !
. Это вывод:
creating directory: excl!dir placing empty file: excl!dirempty_18378.txt adequately escaped `!`: improperly escaped `!`: found item: empty_18378.txt found item: empty_18378.txt found item: empty_18378.txt
я ожидаю, что каталог будет перечислен в случае восклицательного знака is на самом деле правильно убежал, иначе нет; но результат показывает противоположное поведение.
подобное явление возникает с for /F
, как в следующем сценарии с !
в строке вариант:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "STRING=EXCLAMATION ^! MARK AND CARET ^^ SYMBOL"
echo/
echo normal expansion: %STRING%
echo delayed expansion: !STRING!
echo/
echo adequately escaped `^^!`:
for /F "tokens=1-2 delims=^!" %%K in ("!STRING!") do echo(%%K -- %%L
for /F tokens^=1-2^ delims^=^^! %%K in ("!STRING!") do echo(%%K -- %%L
echo/
echo improperly escaped `^^!`:
for /F "tokens=1-2 delims=!" %%K in ("!STRING!") do echo(%%K -- %%L
for /F tokens^=1-2^ delims^=! %%K in ("!STRING!") do echo(%%K -- %%L
for /F tokens^=1-2^ delims^=^! %%K in ("!STRING!") do echo(%%K -- %%L
endlocal
exit /B
выход выглядит так, странно:
normal expansion: EXCLAMATION MARK AND CARET SYMBOL delayed expansion: EXCLAMATION ! MARK AND CARET ^ SYMBOL adequately escaped `!`: EXCLAMATION -- MARK AND CARET EXCLAMATION -- MARK AND CARET improperly escaped `!`: EXCLAMATION -- MARK AND CARET ^ SYMBOL EXCLAMATION -- MARK AND CARET ^ SYMBOL EXCLAMATION -- MARK AND CARET ^ SYMBOL
здесь я ожидаю, что вся строка будет разделена ровно на два токена:EXCLAMATION
и MARK AND CARET ^ SYMBOL
. Но второй токен слишком короткий, все, начиная с символа каретки ^
отсутствует; поэтому я заключаю, что ^
используется для побега !
это воспринимать буквально. При отсутствии (или плохом) побеге возвращенные маркеры являются предполагаемыми.
1 ответов
варианты FOR
, IF
и REM
анализируются только до специальной фазы символов.
Или лучше команды обнаруживаются в специальной фазе символов, и тогда активируется другой парсер.
поэтому в опциях невозможно использовать отложенное расширение или параметр FOR.
тесты с ошибками
for /F %%O in ("defined") do (
if %%O var echo yes
)
set option=defined
if !option! var echo yes
это, кажется, работает, но использует неправильные разделители (D
, e
, i
, l
, m
, s
, y
и !
)
set "myDelims=123"
for /F "tokens=1,2 delims=!myDelims!" %%A in ("Hello 1 world") do (
echo Token1=%%A Token2=%%B
)
и для REM
set "help=/?"
REM !HELP! - No help will be shown