解释Windows批量换行变量hack的工作原理

mat*_*kie 67 batch-file

有人可以解释这是如何工作的吗?

@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.
Run Code Online (Sandbox Code Playgroud)

发出:

There should be a newline
inserted here.
Run Code Online (Sandbox Code Playgroud)

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

jeb*_*jeb 87

该技巧使用了插入符的行为.
Long命令中也解释了在Windows Vista批处理(.bat)文件中拆分多行

插入符号是下一个字符的转义字符,或者在行结束时它用作多行字符,但这几乎是相同的.

在行尾,它只是逃避下一个字符,在这种情况下是<Linefeed>,但是有一个隐藏的功能,所以如果转义的字符是a,<LF>它将被忽略,下一个字符被读取和转义,但这个字符将始终被转义,即使它也是一个<LF>.

现在你可以理解了

set NLM=^


rem Two empty lines are required here
Run Code Online (Sandbox Code Playgroud)

NLM变量只包含一个<LF>字符.但是如果你尝试使用它echo Line1%NLM%Line2失败了,因为解析器停止在单个解析<LF>.
但这很有效

echo Line1^

Line2
Run Code Online (Sandbox Code Playgroud)

因此,您需要在行中添加转义换行符,即NL-Variable.NL变量只包含三个字符.
NL=^<LF><LF> 如果这是扩展的,它只会在插入符号被忽略后创建一个转义<LF>为第一个<LF>.

顺便说一句.在我看来,使用延迟扩展的换行更容易,因为没有必要逃避任何事情.
在这个例子中,我使用%=EMPTY=%而不是空行(用于自我评论),但由于变量=EMPTY=不存在,它将扩展为空行.

setlocal EnableDelayedExpansion
(set NLM=^
%=EMPTY=%
)
echo Line1!NLM!Line2
Run Code Online (Sandbox Code Playgroud)

编辑:附加一些有用的提示使用<LF>

1)用它作为换行符 echo

setlocal EnableDelayedExpansion
(set LF=^
%=EMPTY=%
)
echo Line1!LF!Line2
Run Code Online (Sandbox Code Playgroud)

2)用它来分割括号内的命令

setlocal EnableDelayedExpansion
(set LF=^
%=EMPTY=%
)
(
    echo Line1%LF%set x=4%LF%echo !x!%LF%
)
Run Code Online (Sandbox Code Playgroud)

3)在FOR/F循环中创建一个(几乎)空的EOL-chararcter,因为<LF>EOL的行分隔符<LF>与空的EOL 相同.

FOR /F ^"eol^=^

delims^=^" %%a in (myFile.php) do echo %%a
Run Code Online (Sandbox Code Playgroud)

4)使用LF在FOR/F循环中分割文本

setlocal EnableDelayedExpansion
(set LF=^
%=EMPTY=%
)
set "var=Content1;Content2"
FOR /F "delims=" %%a in ("%var:;=!LF!%") do (
  echo %%a
)
Run Code Online (Sandbox Code Playgroud)


was*_*was 5

似乎有一种方法也适用于管道:

(echo 1st line^
&echo 2nd line) | sort
Run Code Online (Sandbox Code Playgroud)