Wyjaśnij, jak działa Windows batch newline variable hack

Czy ktoś może wyjaśnić, jak to działa?

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

Emituje:

There should be a newline
inserted here.

z Jak można echo nowej linii w plikach wsadowych?

 62
Author: Gerhard Barnard, 2011-06-17

2 answers

Sztuczka wykorzystuje zachowanie karetki.
Wyjaśniono również w Długie polecenia podzielone na wiele linii w Windows Vista batch (.bat) plik

Karetka jest znakiem escape dla następnego znaku lub na końcu linii jest używana jako znak wielowierszowy, ale jest to prawie takie samo.

Na końcu linii po prostu ucieka następny znak, w tym przypadku <Linefeed>, ale istnieje ukryta cecha, więc jeśli znak ucieczki jest <LF> jest ignorowany i następny znak jest odczytywany i uciekany, ale ten charater będzie zawsze uciekany, nawet jeśli jest to również <LF>.

Teraz możesz zrozumieć

set NLM=^


rem Two empty lines are required here

Zmienna NLM zawiera dokładnie jeden znak <LF>. Ale jeśli spróbujesz użyć go z echo Line1%NLM%Line2, nie powiedzie się, ponieważ parser przestaje parsować na pojedynczym <LF>.
Ale to działa

echo Line1^

Line2

Więc musisz dodać do linii unikalny strumień liniowy i jest to zmienna NL. Zmienna NL składa się tylko z trzech postaci.
NL=^<LF><LF> Jeśli ta opcja jest rozszerzona, tworzy tylko jeden znak ucieczki <LF> jako pierwszy <LF> po tym, jak karetka zostanie zignorowana.

Btw. Moim zdaniem o wiele łatwiej jest używać linefeedów z opóźnioną ekspansją, ponieważ nie ma potrzeby ucieczki od czegokolwiek.
W tym przykładzie używam %=EMPTY=% zamiast pustej linii (do samodzielnego komentowania), ale ponieważ zmienna =EMPTY= nie może istnieć, zostanie rozszerzona do pustej linii.

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

EDIT: Dołącz kilka wskazówek przydatnych korzystanie z <LF>

1) Użyj go jako newline w echo

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

2) Użyj go do dzielenia poleceń w bloku nawiasów

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

3) Utwórz (prawie) pusty EOL-character w pętli FOR / F, ponieważ <LF> jest ogranicznikiem linii, EOL z <LF> jest taki sam jak pusty.

FOR /F ^"eol^=^

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

4) Użyj LF do dzielenia tekstu w pętli FOR /F

setlocal EnableDelayedExpansion
(set LF=^
%=EMPTY=%
)
set "var=Content1;Content2"
FOR /F "delims=" %%a in ("%var:;=!LF!%") do (
  echo %%a
)
 85
Author: jeb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-20 06:46:06

Wydaje się, że istnieje sposób , który również działa z rurami:

(echo 1st line^
&echo 2nd line) | sort
 5
Author: was,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-01 15:02:29