为什么在`for / F`或`for / R`参数中不需要跳过感叹号? [英] Why is escaping exclamation marks not necessary in parameter of `for /F` or `for /R`?
问题描述
启用延迟扩展后,(通常)必须正确地转义感叹号( ^^!
),或者在,
!
)。
然而,为什么不能在 / R
或 / F
之后紧接着提供的参数中逃脱必要的惊叹号,开关的为
循环命令?
通过上述转义规则,我使用作为/ R
创建了以下批处理脚本,并且使用!
它的名字(在 / R
选项之后): code> @echo off
setlocal EnableExtensions EnableDelayedExpansion
$ b $ setTARGET = excl ^!dir
setFILE = empty_ %RANDOM%.txt
echo /
创建目录:!TARGET!
mkdir!TARGET!
回显放置空文件:!TARGET!\%FILE%
> !!TARGET!\%FILE%break
echo /
echo完全转义^^!`:
for / Rexcl ^!dir%% F in *)echo echo(找到的项目:%%〜nxF
for / R excl ^^!dir %% F in(*。*)do echo(found item:%%〜nxF
echo /
echo不正确地转义了`^^!`:
for / Rexcl!dir%% F in(*。*)do echo(found item:%%〜nxF
for / R excl!dir %% F in(*。*)do echo(找到的项目:%%〜nxF
for / R excl ^!dir %% F in(*。* )echo(找到的项目:%%〜nxF
擦除!TARGET!\%FILE%
rmdir!TARGET!
endlocal
exit / B
令人惊讶的是,目录仅枚举,没有转义!
这是一个输出:
创建目录:excl!dir
放置空文件:excl!dir\empty_18378.txt
充分转义`!`:
不正确地转义`!`:
找到的项目:empty_18378.txt
找到的项目:empty_18378.txt
找到的项目:empty_18378.txt
我希望在感叹号 实际上正确转义的情况下枚举目录,否则不会;但是结果显示出相反的行为。
类似的现象出现在 code>,如下面的脚本中的!
在选项字符串中:
setSTRING = EXCLAMATION ^!MARK AND CARET ^^ SYMBOL
echo /
回声正常扩展:%STRING%
回声延迟扩展:!STRING!
echo /
echo完全逃脱`^^!`:
for / Ftokens = 1-2 delims = ^! %!K in(!STRING!)echo(%% K - %% L
for / F tokens ^ = 1-2 ^ delims ^ = ^^!%% K in(!STRING !)do echo(%% K - %% L
echo /
echo不正确地转义了^^!`:
for / Ftokens = 1-2 delims =! (!STRING!)中的%% K在(!STRING!)中执行echo(%% K - %% L
/ F令牌^ = 1-2 ^ delims ^ =!%% K )echo(%% K - %% L
for / F tokens ^ = 1-2 ^ delims ^ = ^!%% K in(!STRING!)do echo(%% K - %% L
endlocal
出口/ B
看起来像这样,奇怪:
正常扩展:扩展标记和符号符号
延迟扩展:EXCLAMATION!MARK和CARET ^ SYMBOL
充分逃脱了!!:
口号 - 马克和CARET
口号 - 马克和CARET
不恰当地逃脱了`!`:
口号 - 标记和卡路里^符号
口号 - 标记和卡路里^符号
口号 - 标记和卡路里^符号
这里我期望整个字符串被拆分成两个令牌: EXCLAMATION
和 MARK AND CARET ^ SYMBOL
。但第二个标记太短,从插入符号 ^
的所有内容都将丢失。所以我得出这样的结论:用于转义!
的 ^
是从字面上理解的。没有(或穷的)转义,返回的标记是预期的。
IF
和 REM
只能分析到特殊字符阶段。 > 或者更好的是在特殊字符阶段检测到命令,然后激活一个不同的分析器。
因此在选项中不可能使用延迟扩展和FOR参数。
这些测试失败错误
$ p $
for / F %% O in(defined)do(
if %% O var echo yes
)
set option = defined
if!option! var echo是
这似乎工作,但使用了错误的分隔符( D
, e
, i
, l
, m
, s
, y
和<$
$ b $ pre $ $ code设置myDelims = 123
for / F
echo Token1 = %% A Token2 = %% B
)
和REM
设置help = /?
REM!帮助! - 没有帮助将显示
When delayed expansion is enabled, it is (usually) necessary to escape exclamation marks properly in order to get literal ones (like ^^!
or, when being in between ""
, ^!
, in order to get a literal !
).
However, why is no escaping of exclamation marks necessary but even distructive within the parameters provided immediately after the /R
or the /F
switch of the for
loop command?
With the aforementioned escaping rules in mind, I created the following batch script using for /R
and as a parameter a directory with an !
in its name (stated after the /R
option):
@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
Surprisingly, the directory is enumerated only without escaping the !
. This is an output:
creating directory: excl!dir placing empty file: excl!dir\empty_18378.txt adequately escaped `!`: improperly escaped `!`: found item: empty_18378.txt found item: empty_18378.txt found item: empty_18378.txt
I expect the directory to be enumerated in case the exclamation mark is in fact properly escaped, otherwise not; but the result shows the opposite behaviour.
A similar phenomenon arises with for /F
, like in the following script with an !
in the option string:
@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
The output looks like this, strangely:
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
Here I expect the whole string to be split into exactly two tokens: EXCLAMATION
and MARK AND CARET ^ SYMBOL
. But the second token is too short, everything beginning from the caret symbol ^
is missing; so I conclude that the ^
used for escaping of the !
is taken literally. With no (or poor) escaping, the returned tokens are the intended ones.
The options of FOR
, IF
and REM
are only parsed up to the special character phase.
Or better the commands are detected in the special character phase and a different parser is activated then.
Therefore it's not possible to use delayed expansion nor FOR-Parameter in the options.
These tests fail with errors
for /F %%O in ("defined") do (
if %%O var echo yes
)
set option=defined
if !option! var echo yes
This seems to work, but uses the wrong delimiters (D
, e
, i
, l
, m
, s
, y
and !
)
set "myDelims=123"
for /F "tokens=1,2 delims=!myDelims!" %%A in ("Hello 1 world") do (
echo Token1=%%A Token2=%%B
)
And for REM
set "help=/?"
REM !HELP! - No help will be shown
这篇关于为什么在`for / F`或`for / R`参数中不需要跳过感叹号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!