Объясните, как работает пакетный взлом новой строки в Windows

Может кто-нибудь объяснить, как это работает?

@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.

выделяет:

There should be a newline
inserted here.

из Как вы можете повторить новую строку в пакетных файлах?

2 ответа

Решение

Трюк использует поведение кареты.
Также объясняется, что длинные команды разбиты на несколько строк в пакетном файле (.bat) Windows Vista.

Символ каретки является escape-символом для следующего символа или в конце строки используется в качестве многострочного символа, но это почти то же самое.

В конце строки просто экранируется следующий символ, в этом случае <Linefeed>, но есть скрытая особенность, поэтому, если экранированный символ <LF> он игнорируется, и следующий символ читается и экранируется, но этот символ всегда будет экранирован, даже если он также <LF>,

Теперь вы можете понять

set NLM=^


rem Two empty lines are required here

Переменная NLM содержит ровно одну <LF> персонаж. Но если вы попытаетесь использовать его с echo Line1%NLM%Line2 это терпит неудачу, поскольку синтаксический анализатор прекращает парсинг в единственном <LF>,
Но это работает

echo Line1^

Line2

Таким образом, вам нужно добавить экранированный перевод строки в строку, и это NL-переменная. Переменная NL состоит только из трех символов.
NL=^<LF><LF>И если это расширяется, он создает только один сбежавший <LF> как первый <LF> после каретки будут игнорироваться.

Btw. На мой взгляд, гораздо проще использовать перевод строки с отложенным расширением, так как не нужно ничего избегать.
В этом примере я использую %=EMPTY=% вместо пустой строки (для самостоятельного комментирования), но как переменная =EMPTY= не может существовать, он будет расширен до пустой строки.

setlocal EnableDelayedExpansion
(set NLM=^
%=EMPTY=%
)
echo Line1!NLM!Line2

РЕДАКТИРОВАТЬ: добавить некоторые советы для полезного использования <LF>

1) Используйте его как перевод строки в echo

setlocal EnableDelayedExpansion
(set LF=^
%=EMPTY=%
)
echo Line1!LF!Line2

2) Используйте его для разделения команд в скобках

setlocal EnableDelayedExpansion
(set LF=^
%=EMPTY=%
)
(
    echo Line1%LF%set x=4%LF%echo !x!%LF%
)

3) Создайте (почти) пустой EOL-символ в цикле FOR /F, как <LF> это разделитель строк EOL <LF> такой же, как пустой.

FOR /F ^"eol^=^

delims^=^" %%a in (myFile.php) do echo %%a

4) Используйте LF для разделения текста в цикле FOR /F

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

Кажется, есть способ, который также работает с pipe:

(echo 1st line^
&echo 2nd line) | sort
Другие вопросы по тегам