使用Long commands split over multiple lines in Windows Vista batch (.bat) file中提到的^
,可以将Windows批处理文件中的长命令拆分为多行。
但是,如果插入符号位于双引号字符串中,则不起作用。例如:
echo "A very long line I want to ^
split into two lines"
这将打印"A very long line I want to ^
并告诉我split
是一个未知命令。
有没有办法解决这个问题?
答案 0 :(得分:22)
我看到了三种可能的解决方法。
1)构建组合多个for-parameters的行。
@echo off
SETLOCAL EnableDelayedExpansion
set "line="
for %%a in ("line1"
"line2"
"line3"
"line4"
) do set line=!line!%%~a
echo !line!
2)在每行末尾留下“引用”
@echo on
SETLOCAL EnableDelayedExpansion
set "line=line1 & x#"^
"line2 & a#"^
"line3 & b #"^
"line4 & c "
set "line=!line:#" "=!"
echo !line!
每行中的第一个空格很重要,因为插入符号用作多行字符,但它也会转义第一个字符,因此报价也会被转义。
所以我在构建线之后替换了那个不合理的#“”。
编辑补充:3)消失的引语
setlocal EnableDelayedExpansion
echo "A very long line I want to !"=!^
split into two lines"
在我看来,这是最好的方式,它可以作为解析器首先看到引号,因此最后一个插入符号将起作用,因为它似乎在引号之外。
但是这个!"=!
表达式将扩展名为"=
的变量,但是这样的变量名不能存在(等号只能作为第一个字符出现),所以它扩展为空。
您还可以创建安全表达式,如果行中有引号或不符号,它们将始终从引号中转义,独立。
!"^"=!
echo This multiline works !"^"=!^
as expected
echo "This multiline works !"^"=!^
too"
如果你想避免延迟扩展,你也可以使用-FOR-Loop之类的
for %%^" in ("") do (
echo "This multiline works %%~"^
too"
)
答案 1 :(得分:9)
最直接的答案是逃避报价。它们将被打印,但就CMD.EXE而言,它们不会在功能上引用内容。
@echo off
echo ^"A very long line I want to ^
split into two lines^"
行中出现的任何特殊字符也必须进行转义,因为它们不再在功能上被引用。
@echo off
echo ^"A very long line I want to ^
split into two lines ^
that also contains special characters ^^ ^& ^| ^> ^< ^"
正如杰布所说,直线延续了下一行的第一个字符。因此,如果下一行的第一个字符恰好是一个特殊字符,则不应该第二次转义。下面的代码将给出与前一个示例完全相同的结果。
@echo off
echo ^"A very long line I want to ^
split into two lines ^
that also contains special characters ^^ ^
& ^| ^> ^< ^"
答案 2 :(得分:3)
我今天想出了自己的方法,我从来没有在任何地方看过它,所以我想我会把它发布在这里。当然,它在客观意义上并不优雅。我会说它有它自己独特的丑陋和一些限制,但我发现它与替代品相比更“符合人体工程学”。
具体来说,这种方法具有不需要逃避任何东西的独特特征,同时仍然执行典型的变量替换。这使我能够获取一些看起来完全符合我想要的字符串,将其分布在多行中,并为每行添加前缀而不更改字符串中的任何其他内容。因此,没有试验和错误需要弄清楚特殊字符和转义字符可能如何相互作用。总的来说,我认为它减少了确定性地在多行上产生复杂字符串变量所需的认知负荷,这对我有好处,因为我不想要努力思考并对偶然的复杂性感到沮丧,比如windows命令的细微差别翻译。此外,类似的技术可以在linux bash上使用,使其有点便携。
注意:我没有彻底测试它,它可能不适用于某些用例,我不知道。然而,这个例子有很多看似麻烦的角色,所以看起来有点健壮。
set IMAGE_NAME=android-arm64
set CMD=docker run --rm
set CMD=%CMD% --platform=linux
set CMD=%CMD% -v %CD%:/work
set CMD=%CMD% dockcross/%IMAGE_NAME%
set CMD=%CMD% /bin/sh -c
set CMD=%CMD% "mkdir build-%IMAGE_NAME% &&
set CMD=%CMD% cd build-%IMAGE_NAME% &&
set CMD=%CMD% cmake .. &&
set CMD=%CMD% cmake --build ."
echo %CMD%
就我而言,这是一个命令,所以我可以用:
运行它%CMD%
我愿意接受有关此方法的任何反馈或建议。也许它甚至可以改进。
答案 3 :(得分:0)
@solvingJ的方法相对于Jeb的变体的明显优势在于,很明显会发生什么,并且在左侧空间中是丑陋的cmd内容,而在右侧则是实际内容。并且可以通过在左侧和右侧之间放置更多空格来提高可读性:
set CMD= docker run --rm
set CMD=%CMD% --platform=linux
set CMD=%CMD% -v %CD%:/work
set CMD=%CMD% dockcross/%IMAGE_NAME%
set CMD=%CMD% /bin/sh -c
set CMD=%CMD% "mkdir build-%IMAGE_NAME% &&
set CMD=%CMD% cd build-%IMAGE_NAME% &&
set CMD=%CMD% cmake .. &&
set CMD=%CMD% cmake --build ."
不幸的是,由于注释中多个空格被缩小为一个,因此无法在注释中进行演示。所以我在回答中实际上只是对@solvingJ回答的评论,我认为是最好的。
答案 4 :(得分:-2)
如果要添加空白行,请确保在第二行的^之前有一个空格
echo Hello world ^ ^ 祝你有美好的一天!