我有这个简单的测试脚本:
echo start
falsey ^
&& echo nope
echo end
falsey
是我为帮助测试而制作的一个小C程序,它只返回1
:
int main(int argc, const char** argv) {
return 1;
}
问题是,当我打开cmd并运行此批处理脚本时,它会在两个&
之间插入几个空格,这自然会导致它错误地回显nope
:
C:\jenkins-foo-test>foo.bat
C:\jenkins-foo-test>echo start
start
C:\jenkins-foo-test>falsey & & echo nope
nope
C:\jenkins-foo-test>echo end
end
我已经找到了一些解决方法,比如在 &&
周围加上引号:
falsey ^
"&&" echo nope
在这种情况下,报价实际上不起作用,请参阅@dbenham's answer了解原因。
删除^
并合并两行:
falsey && echo nope
或在&&
:
falsey ^
&& echo nope
这三个选项中的每一个都不能正确打印nope
。但是当cmd.exe打印出正在运行的命令时,它们仍然会有额外的空格。
那么为什么要插入这些额外的空格?如何阻止cmd.exe破坏事物而不必将我的代码始终扭曲成温和不自然的形状?
答案 0 :(得分:8)
The line continuation ^
escapes the first character on the next line,因此第一个&
被视为文字,并作为参数传递给falsey
。第二个&
被视为简单的命令连接。
将&&
视为条件命令连接的一个简单解决方案是将&&
放在行之前:
falsey &&^
echo nope
或者你可以在&&
falsey ^
&& echo nope
另一种选择是使用jeb在他的链接答案中指出的重定向技巧,但我从不使用该技巧。
关于引用"&&"
的“解决方案” - 你自欺欺人。它似乎在falsey失败时起作用。但是如果你的命令成功,那你就麻烦了:
echo ONE ^
"&&" echo TWO
- 输出 -
C:\test>echo ONE " && " echo TWO
ONE "
'" echo TWO' is not recognized as an internal or external command,
operable program or batch file.
请注意,&&
有效,因为第一个"
已转义,因此未引用&&
。如果您在"&&"
echo ONE^
"&&" echo TWO
然后你得到以下
C:\test>echo ONE "&&" echo TWO
ONE "&&" echo TWO
因为现在空间被转义并引用"&&"
。
关于您的评论,您可以忽略这些额外的空格 - 它们是解析器在ECHO为ON时如何显示行的工件。解析器通常会重新排列行,但通常不会影响结果。
例如
< nul set test=OK
echo [%test%]
- 输出 -
C:\test>set test=OK 0<nul
C:\test>echo [OK]
[OK]
注意回显的SET线是如何完全重新排列的。重定向被压缩并移动到语句的末尾,在重定向之前有一个空格。您可能认为该空间将包含在作业中,但您可以看到它不是: - )
如果在管道中使用该命令,那么你唯一可能不得不担心重新安排。
例如:
(set test=OK&call echo [%%^^test%%])|findstr "^"
- 输出 -
C:\test>(set test=OK & call echo [%^test%] ) | findstr "^"
[OK ]
您可以看到SET值中包含一个不需要的额外空间。这是如何实现管道的工件 - 每个端都在新的CMD.EXE进程中执行,并且该行被多次解析。您可以使用%CMDCMDLINE%
显示传递给左侧cmd.exe的命令行,以查看空间的来源。
(set test=OK&call echo [%%^^test%%] %%^^cmdcmdline%%)|findstr "^"
- 输出 -
C:\test>(set test=OK & call echo [%^test%] %^cmdcmdline% ) | findstr "^"
[OK ] C:\WINDOWS\system32\cmd.exe /S /D /c" ( set test=OK & call echo [%^test%] %^cmdcmdline% )"
有关带管道的许多怪癖的更多信息,请参阅Why does delayed expansion fail when inside a piped block of code?。特别是,要注意所选答案,以便对正在发生的事情做出正确解释。