将换行符附加到要 "echo"ed 的变量
Appending newlines to a variable to be "echo"ed out
过去 12 年我一直在 Linux 工作,之前使用 Windows 和命令行,最近不得不恢复那些批处理文件技能,以便于使用/ 编辑实用程序。但是,我在找出如何使用换行符构建字符串变量时遇到了一些问题(相当于 Linux 的 echo -e "Line1\nLine2"
)
基本上我的实用程序会询问用户三个问题并检查输入的有效性。如果有效性失败,每个输入都有一个略有不同的“错误消息”。然后我检查 errMsg
变量是否包含任何内容,如果包含,它会列出来自 3 次有效性检查的整理错误消息。除了错误消息在一行之外,这一切都完美无缺,我想将每个错误放在它自己的行上。然后我“仅仅”在字符串中添加换行符......这就是这个问题的症结所在。
我使用 this link 作为参考点并使用基本字符串,新行按预期出现。但是,当我使用变量时,新行不会出现,我希望有人能向我解释原因。
我有以下代码片段
@echo off
setlocal enableextensions enabledelayedexpansion
set \n=^
set NL=^^^%\n%%\n%^%\n%%\n%
echo This does indeed put in a newline%NL%and this is the 2nd line
:: output follows:
::This does indeed put in a newline
::and this is the 2nd line
set var=Line1%NL%
set var=%var%Line2%NL%
:: output follows:
::Line1Line2
set errMsg=This would be the first custom error message%NL%
set errMsg=%errMsg%This would be the second custom error message%NL%
set errMsg=%errMsg%This would be the third custom error message%NL%
:: output follows
::This would be the first custom error messageThis would be the third custom error message
显然,此时我希望 Line1Line2 示例分为两行,然后最后一个示例将所有自定义错误消息分为三行(而实际上,它缺少第二个/中间的错误消息也是)
任何人都可以向我解释为什么这没有按预期工作吗?我想知道它是否与延迟扩展有关(我相信我需要:这个片段是一个更长的文件的一部分,它确实需要延迟扩展)。有没有更好的(或仅仅是替代的)方法来完成我正在寻找的东西?!
创建一个新的行变量是一个好的开始。但是你应该以不同的方式使用它。
百分比扩展不能很好地处理变量中的换行符,可以做到,但相当复杂。
但是延迟扩展完美地适用于任何角色
@echo off
setlocal EnableDelayedExpansion
(set \n=^
%=empty line=%
)
echo Line1!\n!Line2
set "multiline_var=First Line!\n!Second Line"
echo !multiline_var!
首先,延迟展开不会影响立即展开的new-lines(或者正确地说,line-feed个字符),因为你使用的是立即展开(%
-)他们。
主要问题是 %
-扩展发生得太早,当变量包含这样的内容时,这似乎会干扰对 line-breaks 的识别。
每次解析器扩展包含 line-breaks 的 %
变量时,line-break 后面的所有内容都会被忽略,因此必须转义它们,从而导致多种转义序列。这可以通过以下脚本进行演示:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem // Define a line-feed character:
set \n=^
rem // Define an escaped line-feed character:
set NL=^^^%\n%%\n%^%\n%%\n%
::rem // Redefine the escaped new-line character; it does not change, because the parser first expands `%`-variables before it recognises line-breaks in them:
::set NL=^^%NL%%NL%
rem // Define multi-escaped sequences needed when the same expanded value passes through the parser several times:
set NLNL=^^^^^^^^^^^^^^%NL%%NL%^^%NL%%NL%^^^^^^%NL%%NL%^^%NL%%NL%
set NLNLNL=^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^%NL%%NL%^^%NL%%NL%^^^^^^%NL%%NL%^^%NL%%NL%^^^^^^^^^^^^^^%NL%%NL%^^%NL%%NL%^^^^^^%NL%%NL%^^%NL%%NL%
::set NLNLNL=^^^^^^^^^^^^^^^^^^^^^^^^%NLNL%%NLNL%^^^^^^^^%NLNL%%NLNL%
echo ---- DEFINITION ----
set NL
echo --------------------
echo !\n! ***** IMMEDIATE EXPANSION ***** !\n!
rem // The more parser passes the more escaping is needed:
echo -- VARIABLE CHECK --
set errMsg=This would be the first custom error message%NLNLNL%
set errMsg
set errMsg=%errMsg%This would be the second custom error message%NLNL%
set errMsg
set errMsg=%errMsg%This would be the third custom error message%NL%
set errMsg
echo -- MESSAGE OUTPUT --
echo %errMsg%
echo --------------------
echo !\n! ***** `CALL` EXPANSION ***** !\n!
echo -- VARIABLE CHECK --
set errMsg=This would be the first custom error message%%NL%%
set errMsg
set errMsg=%errMsg%This would be the second custom error message%%NL%%
set errMsg
set errMsg=%errMsg%This would be the third custom error message%%NL%%
set errMsg
echo -- MESSAGE OUTPUT --
call echo %errMsg%
echo --------------------
echo !\n! ***** DELAYED EXPANSION ***** !\n!
echo -- VARIABLE CHECK --
set errMsg=This would be the first custom error message!\n!
set errMsg
set errMsg=!errMsg!This would be the second custom error message!\n!
set errMsg
set errMsg=!errMsg!This would be the third custom error message!\n!
set errMsg
echo -- MESSAGE OUTPUT --
echo !errMsg!
echo --------------------
endlocal
exit /B
这是相关的命令提示符输出:
---- DEFINITION ----
NL=^
NLNL=^^^^^^^
^
^^^
^
NLNLNL=^^^^^^^^^^^^^^^
^
^^^
^
^^^^^^^
^
^^^
^
--------------------
***** IMMEDIATE EXPANSION *****
-- VARIABLE CHECK --
errMsg=This would be the first custom error message^^^^^^^
^
^^^
^
errMsg=This would be the first custom error message^^^
^
This would be the second custom error message^^^
^
errMsg=This would be the first custom error message^
This would be the second custom error message^
This would be the third custom error message
-- MESSAGE OUTPUT --
This would be the first custom error message
This would be the second custom error message
This would be the third custom error message
--------------------
***** `CALL` EXPANSION *****
-- VARIABLE CHECK --
errMsg=This would be the first custom error message%NL%
errMsg=This would be the first custom error message%NL%This would be the second custom error message%NL%
errMsg=This would be the first custom error message%NL%This would be the second custom error message%NL%This would be the third custom error message%NL%
-- MESSAGE OUTPUT --
This would be the first custom error message
This would be the second custom error message
This would be the third custom error message
--------------------
***** DELAYED EXPANSION *****
-- VARIABLE CHECK --
errMsg=This would be the first custom error message
errMsg=This would be the first custom error message
This would be the second custom error message
errMsg=This would be the first custom error message
This would be the second custom error message
This would be the third custom error message
-- MESSAGE OUTPUT --
This would be the first custom error message
This would be the second custom error message
This would be the third custom error message
--------------------
在IMMEDIATE EXPANSION
部分,当命令行多次通过解析过程时,需要复杂的转义序列来维护line-breaks。
<code>CALL
EXPANSION 部分说明了一种更简单的方法,使用 call
命令,它引入了另一个解析阶段,它让文字字符串部分 %NL%
被扩展,它实际上包含在 errMsg
变量而不是 line-breaks 中。请注意,call
很慢,并且有 side-effects,如插入符-(^
-)加倍和丢失 &
、|
、<
>
在某些情况下。
最好的选择当然是使用延迟扩展,如 DELAYED EXPANSION
部分所示,因为这允许变量 errMsg
实际上包含 line-breaks 并安全地扩展它们而不用过早被解析器识别。
过去 12 年我一直在 Linux 工作,之前使用 Windows 和命令行,最近不得不恢复那些批处理文件技能,以便于使用/ 编辑实用程序。但是,我在找出如何使用换行符构建字符串变量时遇到了一些问题(相当于 Linux 的 echo -e "Line1\nLine2"
)
基本上我的实用程序会询问用户三个问题并检查输入的有效性。如果有效性失败,每个输入都有一个略有不同的“错误消息”。然后我检查 errMsg
变量是否包含任何内容,如果包含,它会列出来自 3 次有效性检查的整理错误消息。除了错误消息在一行之外,这一切都完美无缺,我想将每个错误放在它自己的行上。然后我“仅仅”在字符串中添加换行符......这就是这个问题的症结所在。
我使用 this link 作为参考点并使用基本字符串,新行按预期出现。但是,当我使用变量时,新行不会出现,我希望有人能向我解释原因。
我有以下代码片段
@echo off
setlocal enableextensions enabledelayedexpansion
set \n=^
set NL=^^^%\n%%\n%^%\n%%\n%
echo This does indeed put in a newline%NL%and this is the 2nd line
:: output follows:
::This does indeed put in a newline
::and this is the 2nd line
set var=Line1%NL%
set var=%var%Line2%NL%
:: output follows:
::Line1Line2
set errMsg=This would be the first custom error message%NL%
set errMsg=%errMsg%This would be the second custom error message%NL%
set errMsg=%errMsg%This would be the third custom error message%NL%
:: output follows
::This would be the first custom error messageThis would be the third custom error message
显然,此时我希望 Line1Line2 示例分为两行,然后最后一个示例将所有自定义错误消息分为三行(而实际上,它缺少第二个/中间的错误消息也是)
任何人都可以向我解释为什么这没有按预期工作吗?我想知道它是否与延迟扩展有关(我相信我需要:这个片段是一个更长的文件的一部分,它确实需要延迟扩展)。有没有更好的(或仅仅是替代的)方法来完成我正在寻找的东西?!
创建一个新的行变量是一个好的开始。但是你应该以不同的方式使用它。
百分比扩展不能很好地处理变量中的换行符,可以做到,但相当复杂。
但是延迟扩展完美地适用于任何角色
@echo off
setlocal EnableDelayedExpansion
(set \n=^
%=empty line=%
)
echo Line1!\n!Line2
set "multiline_var=First Line!\n!Second Line"
echo !multiline_var!
首先,延迟展开不会影响立即展开的new-lines(或者正确地说,line-feed个字符),因为你使用的是立即展开(%
-)他们。
主要问题是 %
-扩展发生得太早,当变量包含这样的内容时,这似乎会干扰对 line-breaks 的识别。
每次解析器扩展包含 line-breaks 的 %
变量时,line-break 后面的所有内容都会被忽略,因此必须转义它们,从而导致多种转义序列。这可以通过以下脚本进行演示:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem // Define a line-feed character:
set \n=^
rem // Define an escaped line-feed character:
set NL=^^^%\n%%\n%^%\n%%\n%
::rem // Redefine the escaped new-line character; it does not change, because the parser first expands `%`-variables before it recognises line-breaks in them:
::set NL=^^%NL%%NL%
rem // Define multi-escaped sequences needed when the same expanded value passes through the parser several times:
set NLNL=^^^^^^^^^^^^^^%NL%%NL%^^%NL%%NL%^^^^^^%NL%%NL%^^%NL%%NL%
set NLNLNL=^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^%NL%%NL%^^%NL%%NL%^^^^^^%NL%%NL%^^%NL%%NL%^^^^^^^^^^^^^^%NL%%NL%^^%NL%%NL%^^^^^^%NL%%NL%^^%NL%%NL%
::set NLNLNL=^^^^^^^^^^^^^^^^^^^^^^^^%NLNL%%NLNL%^^^^^^^^%NLNL%%NLNL%
echo ---- DEFINITION ----
set NL
echo --------------------
echo !\n! ***** IMMEDIATE EXPANSION ***** !\n!
rem // The more parser passes the more escaping is needed:
echo -- VARIABLE CHECK --
set errMsg=This would be the first custom error message%NLNLNL%
set errMsg
set errMsg=%errMsg%This would be the second custom error message%NLNL%
set errMsg
set errMsg=%errMsg%This would be the third custom error message%NL%
set errMsg
echo -- MESSAGE OUTPUT --
echo %errMsg%
echo --------------------
echo !\n! ***** `CALL` EXPANSION ***** !\n!
echo -- VARIABLE CHECK --
set errMsg=This would be the first custom error message%%NL%%
set errMsg
set errMsg=%errMsg%This would be the second custom error message%%NL%%
set errMsg
set errMsg=%errMsg%This would be the third custom error message%%NL%%
set errMsg
echo -- MESSAGE OUTPUT --
call echo %errMsg%
echo --------------------
echo !\n! ***** DELAYED EXPANSION ***** !\n!
echo -- VARIABLE CHECK --
set errMsg=This would be the first custom error message!\n!
set errMsg
set errMsg=!errMsg!This would be the second custom error message!\n!
set errMsg
set errMsg=!errMsg!This would be the third custom error message!\n!
set errMsg
echo -- MESSAGE OUTPUT --
echo !errMsg!
echo --------------------
endlocal
exit /B
这是相关的命令提示符输出:
---- DEFINITION ---- NL=^ NLNL=^^^^^^^ ^ ^^^ ^ NLNLNL=^^^^^^^^^^^^^^^ ^ ^^^ ^ ^^^^^^^ ^ ^^^ ^ -------------------- ***** IMMEDIATE EXPANSION ***** -- VARIABLE CHECK -- errMsg=This would be the first custom error message^^^^^^^ ^ ^^^ ^ errMsg=This would be the first custom error message^^^ ^ This would be the second custom error message^^^ ^ errMsg=This would be the first custom error message^ This would be the second custom error message^ This would be the third custom error message -- MESSAGE OUTPUT -- This would be the first custom error message This would be the second custom error message This would be the third custom error message -------------------- ***** `CALL` EXPANSION ***** -- VARIABLE CHECK -- errMsg=This would be the first custom error message%NL% errMsg=This would be the first custom error message%NL%This would be the second custom error message%NL% errMsg=This would be the first custom error message%NL%This would be the second custom error message%NL%This would be the third custom error message%NL% -- MESSAGE OUTPUT -- This would be the first custom error message This would be the second custom error message This would be the third custom error message -------------------- ***** DELAYED EXPANSION ***** -- VARIABLE CHECK -- errMsg=This would be the first custom error message errMsg=This would be the first custom error message This would be the second custom error message errMsg=This would be the first custom error message This would be the second custom error message This would be the third custom error message -- MESSAGE OUTPUT -- This would be the first custom error message This would be the second custom error message This would be the third custom error message --------------------
在IMMEDIATE EXPANSION
部分,当命令行多次通过解析过程时,需要复杂的转义序列来维护line-breaks。
<code>CALL
EXPANSION 部分说明了一种更简单的方法,使用 call
命令,它引入了另一个解析阶段,它让文字字符串部分 %NL%
被扩展,它实际上包含在 errMsg
变量而不是 line-breaks 中。请注意,call
很慢,并且有 side-effects,如插入符-(^
-)加倍和丢失 &
、|
、<
>
在某些情况下。
最好的选择当然是使用延迟扩展,如 DELAYED EXPANSION
部分所示,因为这允许变量 errMsg
实际上包含 line-breaks 并安全地扩展它们而不用过早被解析器识别。