当启用延迟扩展时,(通常)需要正确转义感叹号以获得文字(例如^^!
,或者当位于""
, ^!
之间时,为了获得文字!
)。
但是,为什么在紧接for
循环命令的/R
或/F
开关后提供的参数中不需要转义感叹号,甚至是破坏性的?
考虑到前面提到的转义规则,我使用
for /R
创建了以下批处理脚本,并将名称中包含!
的目录作为参数(在/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
我希望在感叹号实际上被正确转义的情况下枚举目录,否则没有;但结果显示相反的行为。
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
。但是第二个标记太短了,从插入符号^
开始的所有内容都缺失了;因此,我得出的结论是,用于转义!
的^
是从字面上理解的。如果没有(或没有)转义,返回的标记就是预期的标记。
FOR
、IF
和REM
的选项只被解析到特殊字符阶段。
或者更好的情况是,在特殊字符阶段检测命令,然后激活不同的解析器。
因此不可能在选项中使用延迟展开或FOR-Parameter。
这些测试失败,并出现错误
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