3

当使用立即扩展(写入而不是批处理文件)时,子字符串扩展在for循环集中(即后面的括号部分)起作用:in%%I%I

set "X=123"
for %I in (%X:~1,1%) do @echo %I

但是,当应用延迟扩展时,它会失败:

for %I in (!X:~1,1!) do @echo %I

我希望输出是:

2

但相反的是:

!X:~1
1!

为什么会这样,我该如何防止呢?

我知道我可以通过引用 set 和 using 来解决这个~问题,但这不是我想要的:

for %I in ("!X:~1,1!") do @echo %~I

以下命令行也失败:

for %I in (!X:*2=!) do @echo %I

意外的输出是:

!

使用,和开关for的命令行也会因此类子字符串语法而失败。/R/L/R

它肯定与,and是, ,等=的标记分隔符这一事实有关。cmdSPACETAB;

4

1 回答 1

1

根据线程Windows命令解释器(CMD.EXE)如何解析脚本?还有很多 评论,答案在于for解析循环的特殊方式。

关键是这个答案的以下摘录(特别是斜体文本):

阶段 2) 处理特殊字符、标记化并构建缓存的命令块:
[...]

  • 三个命令得到特殊处理 - IF、FOR 和 REM
    [...]
    • FOR 在 DO 之后一分为二。FOR 构造中的语法错误将导致致命的语法错误。
    • 通过 DO 的部分是贯穿第 7 阶段的实际 FOR 迭代命令
      • 所有 FOR 选项都在第 2 阶段完全解析。
      • IN 带括号的子句<LF>视为<space>. 解析 IN 子句后,将所有标记连接在一起以形成单个标记。
      • 连续的标记分隔符在整个 FOR 命令中通过 DO 折叠成一个空格。

由于在解析for和所描述的行为之后发生延迟扩展,像SPACE, TAB, ,, ;,=等标记分隔符被转换为单个SPACE, 因此子字符串扩展表达式!X:~1,1!更改为!X:~1 1!, 子字符串替换表达式 like!X:*2=!更改为!X:*2 !,两者都是无效语法。

因此,要解决该问题,您需要通过以下方式转义令牌分隔符^

for %I in (!X:~1^,1!) do @echo %I

和:

for %I in (!X:*2^=!) do @echo %I

(顺便说一句,if语句有一个非常相似的问题。)

于 2018-05-22T13:46:22.180 回答