可以使用
^
将 Windows 批处理文件中的长命令拆分为多行,如 Windows Vista 批处理 (.bat) 文件中的长命令拆分为多行。
但是,如果插入符号位于双引号字符串内,则它将不起作用。例如:
echo "A very long line I want to ^
split into two lines"
这将打印
"A very long line I want to ^
并告诉我 split
是一个未知命令。
有办法解决这个问题吗?
我看到了三种可能的解决方法。
1) 构建组合多个 for 参数的行。
@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"
在我看来,这是“最好的”方式,它的工作原理是解析器首先看到引号,因此最后一个插入符将起作用,因为它似乎在引号之外。
但是这个 !="!
表达式将扩展名为
="
的变量,但是这样的变量名不能存在(等号不能作为第一个字符出现),所以它扩展为空。您还可以创建 safe 表达式,它们总是会在引号之外转义,无论行中是否有引号,它们都是独立的。
!="^"!
echo This multiline works !="^"!^
as expected
echo "This multiline works !="^"!^
too"
如果你想避免延迟扩展,你也可以使用类似 -FOR-Loop
for %%^" in ("") do (
echo "This multiline works %%~"^
too"
)
%%"
@echo off
for /F "tokens=* delims=X" %%^" in ("X") do (
echo %%" No problem with special |&<> characters
echo %%" And &|<> using multi line %%"^
with carets works too
)
@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 ^^ ^& ^| ^> ^< ^"
正如jeb所说,行继续转义了下一行的第一个字符。因此,如果下一行的第一个字符恰好是特殊字符,则不应对其进行第二次转义。下面的代码将成功转义
&
,同时还引入了新行。
@echo off
echo ^"A very long line I want to ^
split into two lines ^
that also contains special characters ^^ ^
& ^| ^> ^< ^"
具体来说,该方法具有不需要转义任何内容的独特特性,同时仍然执行典型的变量替换。这使我能够获取一些看起来完全符合我想要的字符串,将其分布在多行中,并向每行添加前缀,而无需更改字符串中的其他任何内容。因此,不需要反复试验来弄清楚特殊字符和转义字符如何相互作用。总的来说,我认为它减少了在多行上确定性地生成复杂字符串变量所需的认知负荷,这对我来说有好处,因为我不想必须努力思考并因偶然的复杂性(例如 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%
我愿意接受有关此方法的任何反馈或建议。 也许它甚至可以改进。
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 答案的评论,我认为这是最好的。
回声你好世界^ ^ 祝你有美好的一天!