考虑这个例子,我启动一个新的“子”实例cmd.exe
,然后尝试在其中设置一个新的环境变量,然后检查它是否设置了正确的值(这是在cmd.exe
Windows 10 中):
>cmd /c "SET OPERATION=NEW & SET O"
OneDrive=C:\Users\user\OneDrive
OPERATION=NEW
OS=Windows_NT
因此,正如https://superuser.com/a/776506/688965- 通过这样做SET O
我会“显示所有以字母“O”开头的变量”,确实,它表明OPERATION
存在一个环境变量,并且它的值为NEW
。到目前为止,一切顺利。
但是,如果我尝试打印环境值,它确实不是扩张:
>cmd /c "SET OPERATION=NEW & echo %OPERATION%"
%OPERATION%
...然而,如果我尝试扩展任何其他环境变量,它起作用了?!:
>cmd /c "SET OPERATION=NEW & echo %OS%"
Windows_NT
为什么会发生这种情况?如何设置环境变量,然后echo
在子 shell 中用一行打印它cmd.exe
?
答案1
为什么会发生这种情况?
%OPERATION%
在设置变量(阶段 7)之前,会先展开(阶段 1)。
看Windows 命令解释器(CMD.EXE)如何解析脚本?血腥细节:
处理批处理文件中的一行代码涉及多个阶段。
以下是各个阶段的简要概述:
阶段 0)读取行:
第 1 阶段)百分比扩展:
阶段 1.5)删除:删除所有回车符(0x0D)
第 2 阶段)处理特殊字符、标记化并构建缓存的命令块:这是一个复杂的过程,受引号、特殊字符、标记分隔符和插入符号转义等因素的影响。
阶段 3)仅当命令块不以 @ 开头,并且 ECHO 在前一步开始时为 ON 时,才回显已解析的命令。
阶段 4) FOR %X 变量扩展:仅当 FOR 命令处于活动状态并且正在处理 DO 后的命令时。
阶段 5)延迟扩展:仅当启用延迟扩展时
阶段 5.3)管道处理:仅当命令位于管道两侧时
阶段5.5)执行重定向:
阶段 6)CALL 处理/插入符号加倍:仅当命令标记是 CALL 时
阶段7)执行:执行命令