为什么在CMD窗口和.CMD文件中使用CALL SET的方式不同?

3

我正在尝试以编程方式使用Windows CMD中的SET字符串操作版本。 SET有两个版本...

SET New_String=%String:Old_Text=New_Text%

在变量String中用New_Text替换Old_Text,并将结果返回到变量New_String中。
SET New_String=%String:~Number_Of_Chars_To_Skip,Number_Of_Chars_To_Keep%

在变量String中跳过Number_Of_Chars_To_Skip个字符后提取Number_Of_Chars_To_Keep个字符,并将结果存储在变量New_String中。

Old_Text, New_Text, Number_Of_Chars_To_Skip, Number_Of_Chars_To_Keep必须都是字面值,而不是变量。因此,典型的用法如下...

SET New_String=%String:abcd=fghi%
SET New_String=%String:~2,4%

这种使用方法是不起作用的...

SET New_String=%String:%Old_Text%=%New_Text%%
SET New_String=%String:~%Skip_Count%,%Keep_Count%%

要执行上述两个SET操作,您需要像这样CALL SET
CALL SET New_String=%%String:%Old_Text%=%New_Text%%%
CALL SET New_String=%%String:~%Skip_Count%,%Keep_Count%%%

因此,我有以下测试代码片段...
所以, 我有下面这个测试代码片段...
SET "Chars=" & SET "String=0123456789" & SET "Skip=1" & SET "Keep=3"
CALL SET Chars=%%String:~%Skip%,%Keep%%%
ECHO Chars="%Chars%" (expected to be "123")

从CMD文件中,这个指令可以正常工作。 CALL 已经被扩展为SET Chars=%string:~1,3%,并返回了预期的结果123。但是,从CMD窗口(具有相同变量)执行完全相同的CALL SET会返回如下结果...
%0123456789Skip%,3%%

为什么这在CMD窗口中不能工作?我查阅了相关资料,但没有找到任何解释。
1个回答

1
根据Windows命令解释器(CMD.EXE)如何解析脚本?的帖子,批处理文件和命令行在解析时有所不同,特别是在环境变量扩展方面。
批处理文件解析器将两个连续的百分号替换为一个字面值,而命令行解析器则不会这样做。因此,在批处理文件中使用CALL SET Chars=%%String:~%Skip%,%Keep%%%可以正常工作,但在cmd中无法正常工作。
要在cmd中实现相同的结果,可以使用以下方法:
CALL SET Chars=%^String:~%Skip%,%Keep%%

实际上,这只是指定了一个名为^String的变量,该变量预计未定义。与批处理文件解析器相反,命令行解析器不会将未定义的变量替换为空字符串,因此^String保持不变。请注意,在%变量扩展之后处理^。变量%Skip%%Keep%按预期扩展,因此结果表达式为SET Chars=%String:~1,3%
要证明这一点,只需执行SET String=something,结果将为ome
请注意,引用的 SET 语法 CALL SET "Chars=%^String:~%Skip%,%Keep%%" 失败了,因为它将转义字符 ^ 隐藏在解析器中。但是,您可以使用转义的引号代替:
CALL SET ^"Chars=%^String:~%Skip%,%Keep%%^"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接