在批处理文件中调用参数包含与号的子程序

ANi*_*sus 6 windows batch-file

如何调用参数为包含与符号 (&) 的变量的子例程?

没有错误,但调用似乎永远不会执行。

例子.bat

@echo off
setlocal enableDelayedExpansion

rem Doesn't work
set val=with^&ampersand
call :Output !val!

rem Works fine
set val=without_ampersand
call :Output !val!
goto End

:Output
set "line=%1"
echo Called: !line!
goto :eof

End:
Run Code Online (Sandbox Code Playgroud)

输出:

调用: without_ampersand

编辑:

不需要使用delayExpansion。它只是在这个例子中使用。不使用 delayExpansion 的方法是首选。

问题的重点是“我如何调用”而不是“我最初如何设置变量”。变量可能来自用户输入或for /f循环(就像我的情况)。

dbe*_*ham 3

批量转义规则非常令人讨厌,但如果您了解规则,则行为是完全可以预测的。

要了解该问题所需的信息,请参阅Windows 命令解释器 (CMD.EXE) 如何解析脚本?在已接受答案的第 1、2、5 和 6 阶段。但祝你好运,尽快吸收这些信息:-)

有两个基本设计问题会导致您的问题: - 第 6 阶段将所有插入符号加倍,然后重新启动第 2 阶段(实际上是阶段 1、1.5 和 2)。- 但第 2 阶段需要&转义为^&。注意一定是单次^,不能是双次!

^让您的方法发挥作用的唯一方法是在第 6 阶段插入符号加倍发生后引入。

@echo off
setlocal enableDelayedExpansion
set "ESC=^"

rem Calling with delayed expansion value
set "val=with%%ESC%%&ampersand"
call :Output !val!

rem Calling with a string literal
call :Output with%%ESC%%^&ampersand

exit /b

:Output
set "line=%1"
echo Called: !line!
goto :eof
Run Code Online (Sandbox Code Playgroud)

ESC 定义为保存^.
第 1 阶段的第一轮扩展%%ESC%%%ESC%
第 1 阶段的第二轮(由第 6 阶段发起)扩展%ESC%^

这完全不切实际,尤其是当您不知道内容是什么时。

将任何值可靠地传递到 CALLed 例程中的唯一明智策略是按引用传递。传递包含字符串值的变量的名称,并使用延迟扩展在子例程中扩展该值。

@echo off
setlocal enableDelayedExpansion
set "val=with&ampersand"
call :Output val
exit /b

:Output
set "line=!%~1!"
echo Called: !line!
exit /b
Run Code Online (Sandbox Code Playgroud)