Erläutern Sie, wie Windows Batch Newline Variable Hack funktioniert

72

Kann mir bitte jemand erklären, wie das funktioniert?

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

emittiert:

There should be a newline
inserted here.

von Wie können Sie eine neue Zeile in Batch-Dateien wiedergeben?

matt wilkie
quelle
Gibt es einen anderen Grund, als eine neue Leerzeile zu erstellen?
Mechaflash
1
Es gibt viele, ich habe einige Erklärungen zu meiner Antwort hinzugefügt
jeb

Antworten:

91

Der Trick nutzt das Verhalten des Carets.
Wird auch unter Lange Befehle erläutert , die in der Windows Vista-Batchdatei (.bat) über mehrere Zeilen verteilt sind

Das Caret ist ein Escape-Zeichen für das nächste Zeichen oder wird am Zeilenende als mehrzeiliges Zeichen verwendet, dies ist jedoch nahezu identisch.

Am Zeilenende wird einfach das nächste Zeichen maskiert , in diesem Fall das <Linefeed>, aber es gibt eine versteckte Funktion. Wenn das maskierte Zeichen also a <LF>ist, wird es ignoriert und das nächste Zeichen wird gelesen und maskiert, aber dieses Zeichen wird immer maskiert. auch wenn es auch ein ist <LF>.

Jetzt kannst du verstehen

set NLM=^


rem Two empty lines are required here

Die NLM-Variable enthält genau ein <LF>Zeichen. Wenn Sie jedoch versuchen, es echo Line1%NLM%Line2damit zu verwenden, schlägt dies fehl, da der Parser das Parsen bei einem einzelnen beendet <LF>.
Aber das funktioniert

echo Line1^

Line2

Sie müssen also einen Escape-Zeilenvorschub in die Zeile einfügen, und das ist die NL-Variable. Die NL-Variable besteht nur aus drei Zeichen.
NL=^<LF><LF> Und wenn dies erweitert wird, wird nur ein Escape <LF>als erstes erstellt, <LF>nachdem das Caret ignoriert wurde.

Übrigens. Meiner Meinung nach ist es viel einfacher, Linefeeds mit verzögerter Erweiterung zu verwenden, da nichts entgangen werden muss.
In diesem Beispiel verwende ich %=EMPTY=%anstelle einer leeren Zeile (zum Selbstkommentieren), aber da die Variable =EMPTY=nicht existieren kann, wird sie zu einer leeren Zeile erweitert.

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

BEARBEITEN: Fügen Sie einige nützliche Hinweise hinzu<LF>

1) Verwenden Sie es als Zeilenumbruch in einem echo

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

2) Verwenden Sie diese Option, um Befehle in einem Klammerblock aufzuteilen

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

3) Erstellen Sie einen (fast) leeren EOL-Charakter in einer FOR / F-Schleife, ebenso <LF>wie der Zeilenbegrenzer, dessen EOL <LF>der gleiche ist wie ein leerer.

FOR /F ^"eol^=^

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

4) Verwenden Sie LF zum Teilen von Text in einer FOR / F-Schleife

setlocal EnableDelayedExpansion
(set LF=^
%=EMPTY=%
)
set "var=Content1;Content2"
FOR /F "delims=" %%a in ("%var:;=!LF!%") do (
  echo %%a
)
jeb
quelle
Tolles Thema! Wie füge ich ein Zeilenumbruchzeichen in eine Zeichenfolge ein, die ich nach dem Erstellen der mehrzeiligen Zeichenfolge wiedergeben werde? Vielen Dank
RGuggisberg
@RGuggisberg Ich bin nicht sicher, ob ich Ihre Frage habe, aber vielleicht meinen Sieset multiStr=Line1!LF!Line2 & echo !multiStr!
jeb
Ahhh ja! Ich habs. Vielen Dank jeb
RGuggisberg
5

Es scheint einen Weg zu geben , der auch mit Pipe funktioniert:

(echo 1st line^
&echo 2nd line) | sort
war
quelle
Dies sortiert aber auch jede Zeile. Dieser Trick funktioniert also nicht zum Verketten mehrzeiliger Dateien
Armin