当使用立即扩展时,子字符串扩展在 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!
为什么会这样,我该如何预防?
我知道我可以通过引用集合并使用 ~
来解决这个问题,但这不是我想要的:
for %I in ("!X:~1,1!") do @echo %~I
下面的命令行也失败了:
for %I in (!X:*2=!) do @echo %I
意外的输出是:
!
此外,使用 /R
、/L
和 /R
开关的 for
命令行也会因此类子命令而失败-字符串语法。
这肯定与 、
和 =
是 cmd
的标记分隔符这一事实有关,就像 SPACE , TAB, ;
等
最佳答案
根据线程 How does the Windows Command Interpreter (CMD.EXE) parse scripts?还有numerous comments在这里,答案在于特殊的方式for
循环被解析。
关键是以下摘录的this answer (特别是斜体):
Phase 2) Process special characters, tokenize, and build a cached command block:
[...]
- Three commands get special handling - IF, FOR, and REM
[...]
- FOR is split in two after the DO. A syntax error in the FOR construction will result in a fatal syntax error.
- The portion through DO is the actual FOR iteration command that flows all the way through phase 7
- All FOR options are fully parsed in phase 2.
- The IN parenthesized clause treats
<LF>
as<space>
. After the IN clause is parsed, all tokens are concatenated together to form a single token.- Consecutive token delimiters collapse into a single space throughout the FOR command through DO.
由于在解析for
之后发生延迟展开以及描述的行为, token 分隔符,如 SPACE、TAB、,
, ;
, =
等转换为单个 SPACE,因此子字符串扩展表达式如 !X:~1,1!
更改为 !X:~1 1!
, 和子字符串替换表达式,如 !X:*2=!
更改为 !X:*2 !
, 它们都是无效的语法。
因此,要解决此问题,您需要通过 ^
转义标记分隔符喜欢:
for %I in (!X:~1^,1!) do @echo %I
和:
for %I in (!X:*2^=!) do @echo %I
(顺便说一句, if
statements 有一个非常相似的问题。)
关于batch-file - 为什么在 IN 之后 FOR 会因延迟子字符串扩展而失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50380393/