Batch file 如何在Windows批处理文件中将双引号行拆分为多行?

Batch file 如何在Windows批处理文件中将双引号行拆分为多行?,batch-file,Batch File,可以使用中提到的^将Windows批处理文件中的长命令拆分为多行 但是,如果插入符号位于双引号字符串中,它将不起作用。例如: echo "A very long line I want to ^ split into two lines" 这将打印一条非常长的行,我想^,并告诉我拆分是一个未知命令 有没有办法解决这个问题?我认为有三种可能的解决办法 1)为多个参数构建组合线。 @echo off SETLOCAL EnableDelayedExpansion set "line=" for

可以使用中提到的
^
将Windows批处理文件中的长命令拆分为多行

但是,如果插入符号位于双引号字符串中,它将不起作用。例如:

echo "A very long line I want to ^
split into two lines"
这将打印一条非常长的行,我想^,并告诉我
拆分
是一个未知命令


有没有办法解决这个问题?

我认为有三种可能的解决办法

1)为多个参数构建组合线。

@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"
在我看来,这是最好的方法,因为解析器首先看到引号,因此最后一个插入符号将起作用,因为它似乎在引号之外。
但是这个
!=“
表达式将展开名为“
=”
”的变量,但这样的变量名不存在(不能以等号作为第一个字符出现),因此它将展开为零

您还可以创建安全表达式,它们将始终从引号中转义,如果行中有引号或没有引号,则它们是独立的。
!=“^”!

如果您想避免延迟扩展,还可以使用类似FOR的循环

for %%^" in ("") do (
echo "This multiline works %%~"^
too"
)

最直截了当的答案是避开引号。它们将被打印出来,但就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 ^^ ^& ^| ^> ^< ^"

我今天想出了我自己的方法,我从来没有在任何地方看到过它的建议,所以我想把它贴在这里。当然,它在客观意义上并不优雅。我想说它有自己独特的丑陋和一些局限性,但我发现它比其他选择更“符合人体工程学”

具体地说,这种方法的独特之处在于不需要转义任何内容,同时仍然执行典型的变量替换。这使我能够获取一些看起来完全符合我需要的字符串,将其分散到多行,并在不更改字符串中任何其他内容的情况下为每行添加前缀。因此,没有trial和error需要找出特殊字符和转义字符如何相互作用。总的来说,我认为它减少了在多行上确定地生成复杂字符串变量所需的认知负载,这对我来说是好的,因为我不想费劲思考,也不想因为像windows命令解释器的细微差别。另外,一种类似的技术也可以在LinuxBash上使用,使其具有一定的可移植性

注意:我还没有完全测试过它,我不知道它在某些用例中可能不起作用。但是,这个例子有很多看起来很麻烦的字符,而且它可以工作,所以它看起来有些健壮

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%

我愿意接受关于这个方法的任何反馈或建议。也许它甚至可以改进。

与Jeb的变体相比,@solvingJ的方法的明显优势在于,发生的事情非常明显,左边是丑陋的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 ."

遗憾的是,在注释中不可能演示这一点,因为多个空格被缩小到一个。因此,我在回答一个实际上是对“SalpjjJ的答案的评论”时,我认为这是最好的。

< P>如果要添加空行,则确保在第二行

之前有一个空格。 回声你好世界^ ^
祝你玩得愉快!

答案并不简单,但这是一些很酷的技巧!我希望我能有多个Upvots。谢谢!我真的很喜欢方法#1。这个方法有什么好的地方吗?它会失败,比如
*?
等字符,并且作为for循环,尝试将它们用作通配符。但是,你可以切换到for/F loopFirst方法worked对我来说,我只是删除了第4行变量周围的引号,因为我得到了一条消息,环境变量不存在。在那之后,它工作得很好。+1,但我更喜欢消失引号,因为你不需要转义特殊字符。我也更喜欢消失引号:-)只要你知道插入符号是转义符角色,我认为这个技巧更容易记住。不需要理解/启用延迟扩展,也不需要理解/记忆延迟扩展黑客。但对每个人来说,这都是自己的。这比公认的答案更好、更清晰、更容易。你永远是最好的。有没有办法创建一个空行?-1:in(UNESCAPED caret
^
)除了
\n
之外的所有字符都失去了意义,因此这将不起作用:
echo“引号打破了这个技巧^next line
%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 ."