为什么在`for / F`或`for / R`参数中不需要跳过感叹号? [英] Why is escaping exclamation marks not necessary in parameter of `for /F` or `for /R`?

查看:316
本文介绍了为什么在`for / F`或`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>,如下面的脚本中的在选项字符串中:

 setlocal EnableExtensions EnableDelayedExpansion 

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 !)

令牌= 1,2分界符=!myDelims! (Hello 1 world)中的%% A do(
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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆