在一个. bat脚本中,我有一个包含&
的变量,需要传递给多个命令,其中一个命令是pipe。
set foo="1 & 2"
command1 --foo %foo% --bar
echo %foo% | command2 --stdin
在尝试了here和here中的各种解决方案之后,我最终将变量的值用引号括起来(而不是转义而不加引号,或者将整个"var = value"用引号括起来)。
这在向命令传递参数时有效;但在管道中使用echo时,引号也会传递给stdin:
setlocal enableExtensions enableDelayedExpansion
set foo="1 & 2"
echo %foo% | sort
输出(如预期):
"1 & 2"
接下来,我添加了延迟扩展以删除引号,但是现在管道符在echo中变成了一个文本字符,而不是同时运行两个命令:
setlocal enableExtensions enableDelayedExpansion
set foo="1 & 2"
echo !foo:"=! | sort
输出:
如何说服脚本实际运行管道,而不是将其变成一个文本字符串?
为了以防万一,我在Windows 10中运行此程序。
- 注意 *:上面使用的
sort
只是一个任意命令的例子,它很方便,因为它获取stdin并将其打印出来,类似于Linux中的cat
命令。
2条答案
按热度按时间lyr7nygr1#
正如Stephan所说,双方都在自己的子进程中执行,这导致了多次解析命令。
你可以通过多次转义来解决它,或者你可以构建一个命令,不需要转义。
一种方法是避免在批处理文件本身中展开,并且只使用一个转义级别。
喜欢
在批处理文件和子进程中将解析双百分比,它变为:
在子进程中使用 late 延迟扩展甚至更好,但有点棘手,因为子进程将在没有启用延迟扩展的情况下启动(注册表项
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\DelayedExpansion
中的默认值为0x 00/OFF),您需要使用一个额外的cmd.exe进程启用它。圆括号避免了批处理文件本身的延迟扩展。
或者对于更复杂的内容,可能在左侧包含IF或FOR循环,我建议在子进程中启动批处理文件本身。
在我的例子中,我使用了蹦床技术。
jtw3ybtb2#
由于管道的两端是在不同的进程中执行的,因此需要对有害字符进行“双转义”(并对其中一个转义字符也进行转义,以便将其传递给第二个示例),这样就产生了 * 三个 * 转义字符: