如何在批处理文件中回显换行符?

如何从批处理文件输出中插入换行符?

我想做这样的事情:

echo hello\nworld

这将输出:

hello
world
1175378 次浏览

用途:

echo hello
echo:
echo world

echo hello & echo.world

这意味着您可以将& echo.定义为换行符\n的常量。

在这里,创建一个. bat文件,其中包含以下内容:

@echo off
REM Creating a Newline variable (the two blank lines are required!)
set NLM=^




set NL=^^^%NLM%%NLM%^%NLM%%NLM%
REM Example Usage:
echo There should be a newline%NL%inserted here.


echo.
pause

您应该会看到如下输出:

There should be a newline
inserted here.


Press any key to continue . . .

显然,您只需要REM语句之间的代码。

当回显重定向到文件时,多个回显命令将无法工作。我想也许“>>”重定向器是一个不错的选择:

echo hello > temp
echo world >> temp

就像Grimtron建议的那样-这里有一个快速的例子来定义它:

@echo off
set newline=^& echo.
echo hello %newline%world

产出

C:\>test.bat
hello
world

这对我很有效,没有必要延迟扩展:

@echo off
(
echo ^<html^>
echo ^<body^>
echo Hello
echo ^</body^>
echo ^</html^>
)
pause

它像这样写输出:

<html>
<body>
Hello
</body>
</html>
Press any key to continue . . .

cmd/bat-files中有一个标准功能echo:来编写空白行,它模拟cmd输出中的新行:

@echo off
echo line1
echo:
echo line2

@echo line1 & echo: & echo line2

上面引用的cmd-file的输出:

line1


line2

就像Ken的回答,但使用了延迟展开。

setlocal EnableDelayedExpansion
(set \n=^
%=Do not remove this line=%
)


echo Line1!\n!Line2
echo Works also with quotes "!\n!line2"

首先创建一个换行字符并分配给\n-变量。
这是因为行尾的插入符号试图转义下一个字符,但如果这是一个换行,它将被忽略,下一个字符将被读取并转义(即使这也是一个换行)。 然后你需要第三个换行来结束当前指令,否则第三行将被附加到LF变量。 即使批处理文件也有CR/LF的行结尾,只有LF很重要,因为CR在解析器的这个阶段被删除了。

使用延迟展开的优点是,根本没有特殊的字符处理。
echo Line1%LF%Line2将失败,因为解析器停止解析单个换行符。

更多的解释在
SO:长命令在Vista/DOS批处理(. bat)文件中拆分多行
SO:Windows命令解释器(CMD.EXE)如何解析脚本?

编辑:避免echo.

这并没有回答问题,因为问题是关于单个echo可以输出多行。

但是,尽管其他答案建议使用echo.来创建新行,但应该注意的是echo.是最糟糕的,因为它非常慢并且可能完全失败,因为cmd.exe搜索名为ECHO的文件并尝试启动它。

对于只打印空行,您可以使用

echo,
echo;
echo(
echo/
echo+
echo=

但是应该避免使用echo.echo\echo:,因为它们可能非常慢,具体取决于脚本将执行的位置,例如网络驱动器。

你也可以这样做,

(for %i in (a b "c d") do @echo %~i)

输出将是,

a
b
c d

请注意,当将其放入批处理文件时,“%”应加倍。

(for %%i in (a b "c d") do @echo %%~i)

如果有人来这里是因为他们想回声MINGW make makefile中的空行,我用

@cmd /c echo.

简单地使用echo.会导致可怕的process_begin: CreateProcess(NULL, echo., ...) failed.错误消息。

我希望这至少能帮助另一个人:)

您可以使用@echo(@echo+[空间]+[可破坏空间])

注意:可破坏空间可以使用Alt+0160获得

希望有帮助:)

[编辑]嗯,你是对的,我需要它在Makefile中,它在那里完美地工作。我想我的答案不适合批处理文件…我的错。

echo.够了。

如果您需要在单行中使用它,请使用&。例如,

echo Line 1 & echo. & echo line 3

将输出为:

Line 1


line 3

现在,假设你想要一些更高级的东西,…

set n=^&echo.
echo hello %n% world

产出

hello
world

然后,只要您想在echo语句中添加新行,就可以添加%n%。这更接近于您在各种语言中使用的\n

故障

set n=将变量n设置为:

^取消下一个要遵循的符号:

&表示在同一行执行另一个命令。我们不关心错误级别(它是大声喊出的回声语句),所以不需要&&

echo.继续回显语句。

所有这些都有效,因为您实际上可以创建代码中的变量,并在其他命令中使用它们。它有点像贫民区函数,因为批处理并不是最先进的shell脚本语言。这只是因为批处理对变量的使用很差,没有自然地在int、字符、浮点数、字符串等之间指定。

如果你很狡猾,你可以让它与其他东西一起工作。例如,用它来回声标签

set t=^&echo.     ::there are spaces up to the double colon

如果您需要将结果放入文件,您可以使用:

(echo a & echo: & echo b) > file_containing_multiple_lines.txt

Ken和Jeb解决方案运行良好。

但是新行仅使用LF字符生成,我需要CRLF字符(Windows版本)。

为此,在脚本的末尾,我将LF转换为CRLF。

示例:

TYPE file.txt | FIND "" /V > file_win.txt
del file.txt
rename file_win.txt file.txt

要批量启动新行,您所要做的就是添加“echo[”,如下所示:

echo Hi!
echo[
echo Hello!

如果需要在可以传递给变量的字符串文字中使用著名的\n,可以编写如下Hello.bat脚本中的代码:

@echo off
set input=%1
if defined input (
set answer=Hi!\nWhy did you call me a %input%?
) else (
set answer=Hi!\nHow are you?\nWe are friends, you know?\nYou can call me by name.
)


setlocal enableDelayedExpansion
set newline=^




rem Two empty lines above are essential
echo %answer:\n=!newline!%

这种方式多行输出可以通过在一个地方准备,甚至在其他scritpt或外部文件中,并在另一个地方打印。

换行符保存在换行符变量中。它的值必须替换为之后回声行被展开,所以我使用启用延迟来启用感叹号,以在执行时展开变量。执行将\n替换为换行符内容(在帮助设置中查找语法)。我们当然可以在设置回答时使用!换行符!,但\n更方便。它可以从外部传递(尝试之后0),其中没有人知道保存换行符的变量的名称(是的,之后1的工作方式相同)。

上面的示例可以细化为子例程或独立批处理,如call:mlecho Hi\nI'm your comuter

:mlecho
setlocal enableDelayedExpansion
set text=%*
set nl=^




echo %text:\n=!nl!%
goto:eof

请注意,额外的反斜杠不会阻止脚本解析\n子字符串。

为什么不使用子字符串/替换空格来echo;

set "_line=hello world"
echo\%_line: =&echo;%
  • 结果:
hello
world
  • 或者,将\n替换为echo;
set "_line=hello\nworld"
echo\%_line:\n=&echo;%

简单

set nl=.
echo hello
echo%nl%
REM without space ^^^
echo World

结果:

hello
world

对于带有虚拟终端序列的Windows 10,存在高度控制光标位置的方法。

要定义转义序列0x1b,可以使用以下内容:

@Echo off
For /f %%a in ('echo prompt $E^| cmd')Do set \E=%%a

要输出字符串之间的单个换行符:

<nul set /p "=Hello%\E%[EWorld"

要输出n换行符,其中n被替换为整数:

<nul set /p "=%\E%[nE"

许多

请注意,这在控制台中不起作用,因为它将模拟转义键并清除该行。

使用此代码,将<ESC>替换为0x1b转义字符或使用此Pastebin链接

:: Replace <ESC> with the 0x1b escape character or copy from this Pastebin:
:: https://pastebin.com/xLWKTQZQ


echo Hello<ESC>[Eworld!


:: OR


set "\n=<ESC>[E"
echo Hello%\n%world!

请注意,根据控制台虚拟终端序列,光标定位使用光标定位的所有解决方案:

序列 代码 特性介绍 行为
ESC[E CNL 光标下一行 从当前位置向下光标

只工作只要没有到达控制台窗口底部

在底部,没有空间可以向下移动光标,所以它只是向左移动(使用CRLFCR),并且之前打印的行从一开始就被覆盖了。

在一个不眠之夜之后,在阅读了这里的所有答案之后,在阅读了很多SS64>CMD之后,在经历了很多尝试和错误之后,我发现:

(几乎)终极解决方案

太长别读

…对于早期采用者。

重要!
使用支持Unicode的C&P文本编辑器,例如Notepad++!

设置换行符环境变量…

…在当前的CMD会议

重要!
请勿在“#EYZ0”和“^”之间编辑任何内容!(中间有一个字符,但你看不到它。既不在这里也不在编辑模式下。C&P在这里工作。)
:: Sets newline variables in the current CMD session
set \n=​^&echo:
set nl=​^&echo:

…对于当前用户

重要!
不要在(第二个)“#EYZ0”和“^”之间编辑任何内容!(中间有一个字符,但你看不到它。既不在这里也不在编辑模式下。C&P在这里工作。)
:: Sets newline variables for the current user [HKEY_CURRENT_USER\Environment]
setx \n ​^&echo:
setx nl ​^&echo:

…用于本地机器

重要!
不要在(第二个)“#EYZ0”和“^”之间编辑任何内容!(中间有一个字符,但你看不到它。既不在这里也不在编辑模式下。C&P在这里工作。)
:: Sets newline variables for the local machine [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]
setx \n ​^&echo: /m
setx nl ​^&echo: /m

为什么几乎?

它不适用于印刷线未配对(打开和关闭)的双引号,除非唯一未配对的双引号是文本的最后一个字符,例如:

  • 作品:""echo %\n%...after "newline". Before "newline"...%\n%...after "newline"(每个印刷线配对)

  • works:echo %\n%...after newline. Before newline...%\n%...after newline"(唯一未配对的双引号是最后一个字符)

  • 不起作用:echo "%\n%...after newline. Before newline...%\n%...after newline"(双引号是未配对在同一个印刷线中)

    完全双引号文本的解决方法(灵感来自Windows批处理:没有新行的回声):

    set BEGIN_QUOTE=echo ^| set /p !="""
    ...
    %BEGIN_QUOTE%
    echo %\n%...after newline. Before newline...%\n%...after newline"
    

它适用于完全单引号的文本,例如:

echo '%\n%...after newline. Before newline...%\n%...after newline'

附加价值:转义字符

说明
在'='之后有一个字符,但您在这里看不到它,而是在编辑模式下。C&P在这里工作。
:: Escape character - useful for color codes when 'echo'ing
:: See https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#text-formatting
set ESC=

有关颜色,请参阅https://imgur.com/a/EuNXEarhttps://gist.github.com/gerib/f2562474e7ca0d3cda600366ee4b8a45

第二个附加价值:轻松获取Unicode字符

一个很棒的页面,可以通过关键字获取87,461个Unicode字符(AToW):https://www.amp-what.com/

的原因

  • 肯的回答中的版本显然有效(我没有尝试过),但不知何故……嗯……你看:

    set NLM=^
    
    
    
    
    set NL=^^^%NLM%%NLM%^%NLM%%NLM%
    
  • user2605194user287293的答案派生的版本(没有'='和'^'之间的任何内容):

    set nl=^&echo:
    set \n=^&echo:
    

    部分工作,但失败,行开头的变量为echoed:

    > echo %\n%Hello%\n%World!
    echo   & echo:Hello & echo:World!
    echo is ON.
    Hello
    World
    

    由于第一个echo的空参数。

  • 所有其他人都或多或少地调用了三个#EYZ。

  • 我喜欢短句。

背后的故事

为了防止此处答案中建议的set \n=^&echo:回响空白(以及此类打印其状态),我第一次想起Alt+255用户是在Novell是一个广泛使用的网络并且使用437850等代码页面的时候。但是现在Unicode中的0d255/0xFF是带diaeresis的拉丁文小写字母Y

然后我想起了Unicode中的更多的空间比普通的0d32/0x20都要多,但它们都被认为是空白,导致与相同的行为。

但是还有更多:零宽度空间加入者不被视为空格。它们的问题是,你无法C&P它们,因为它们的宽度为零,没有什么可选择的。所以,我复制了一个接近其中之一的毛发空间(U+200A),就在零宽度空间(U+200B)之前到Notepad++中,打开了它的十六进制编辑器插件,找到了它的位表示E2 80 8A并将其更改为E2 80 8B。成功!我有一个在我的\n环境变量中不可见的非空白字符。

在Ken的答案中添加一个变体,显示环境变量的设置值,其中包含新行。

我们使用此方法将错误条件附加到VAR中的字符串,然后在所有错误检查结束时将输出到文件中作为所有错误的摘要。

这不是完整的代码,只是一个例子。

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
:: the two blank lines are required!
set NLM=^




set NL=^^^%NLM%%NLM%^%NLM%%NLM%
:: Example Usage:


Set ErrMsg=Start Reporting:
:: some logic here finds an error condition and appends the error report
set ErrMsg=!ErrMsg!!NL!Error Title1!NL!Description!NL!Summary!NL!


:: some logic here finds another error condition and appends the error report
set ErrMsg=!ErrMsg!!NL!Error Title2!NL!Description!NL!Summary!NL!


:: some logic here finds another error condition and appends the error report
set ErrMsg=!ErrMsg!!NL!Error Title3!NL!Description!NL!Summary!NL!


echo %ErrMsg%
pause
echo %ErrMsg% > MyLogFile.log

日志和屏幕输出看起来像这样…

脚本的日志输出

脚本的屏幕输出