Sie können verschiedene Ansätze wählen, je nachdem, ob die awk
Behandlung RS
als einzelnes Zeichen (wie bei herkömmlichen awk
Implementierungen) oder als regulärer Ausdruck (wie bei gawk
oder mawk
) erfolgt. Leere Dateien sind auch schwierig zu betrachten, da sie awk
zum Überspringen neigen.
gawk
, mawk
Oder andere , awk
wo Implementierungen RS
kann ein regulärer Ausdruck sein.
In diesen Implementierungen (zum Beispiel mawk
: Beachten Sie, dass einige Betriebssysteme wie Debian eine sehr alte Version anstelle der von @ThomasDickey gepflegten modernen Version liefern ), RS
ist das Datensatztrennzeichen dieses Zeichen, wenn es ein einzelnes Zeichen enthält, oder wird awk
in den Absatzmodus versetzt , wenn RS
es leer ist. oder behandelt RS
als regulären Ausdruck anders.
Die Lösung besteht darin, einen regulären Ausdruck zu verwenden, der möglicherweise nicht übereinstimmt. Manche kommen wie x^
oder in den Sinn $x
( x
vor dem Start oder nach dem Ende). Einige (besonders mit gawk
) sind jedoch teurer als andere. Bisher habe ich festgestellt, dass dies ^$
das effizienteste ist. Es kann nur auf eine leere Eingabe passen, aber dann gäbe es nichts, gegen das man passen könnte.
Wir können also:
awk -v RS='^$' '{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
Eine Einschränkung ist jedoch, dass leere Dateien übersprungen werden (im Gegensatz zu perl -0777 -n
). Dies kann mit GNU behoben awk
werden, indem der Code ENDFILE
stattdessen in eine Anweisung geschrieben wird. Wir müssen aber auch $0
in einer BEGINFILE-Anweisung zurücksetzen, da sie sonst nach der Verarbeitung einer leeren Datei nicht zurückgesetzt würde:
gawk -v RS='^$' '
BEGINFILE{$0 = ""}
ENDFILE{printf "%s: <%s>\n", FILENAME, $0}' file1 file2...
traditionelle awk
Implementierungen, POSIXawk
In diesen Fällen RS
handelt es sich nur um ein Zeichen, sie haben kein BEGINFILE
/ ENDFILE
, sie haben keine RT
Variable, sie können das NUL-Zeichen auch im Allgemeinen nicht verarbeiten.
Sie würden denken, dass using RS='\0'
dann funktionieren könnte, da sie ohnehin keine Eingaben verarbeiten können, die das NUL-Byte enthalten, aber nein, das wird RS='\0'
in traditionellen Implementierungen als behandelt RS=
, was der Absatzmodus ist.
Eine Lösung kann darin bestehen, ein Zeichen zu verwenden, das in der Eingabe nicht vorkommt \1
. In Gebietsschemas für Mehrbytezeichen können Sie sogar Byte-Sequenzen erstellen, die sehr unwahrscheinlich sind, da sie nicht zugewiesene Zeichen oder Nicht-Zeichen wie $'\U10FFFE'
in UTF-8-Gebietsschemas bilden. Nicht wirklich kinderleicht und Sie haben auch ein Problem mit leeren Dateien.
Eine andere Lösung kann darin bestehen, die gesamte Eingabe in einer Variablen zu speichern und diese am Ende in der END-Anweisung zu verarbeiten. Das heißt, Sie können jedoch immer nur eine Datei gleichzeitig verarbeiten:
awk '{content = content $0 RS}
END{$0 = content
printf "%s: <%s>\n", FILENAME, $0
}' file
Das ist das Äquivalent von sed
's:
sed '
:1
$!{
N;b1
}
...' file1
Ein weiteres Problem bei diesem Ansatz ist, dass, wenn die Datei nicht mit einem Zeilenumbruchzeichen endete (und nicht leer war), $0
am Ende noch eines willkürlich hinzugefügt wird (mit würden gawk
Sie das umgehen, indem Sie RT
anstelle von RS
in das verwenden Code oben). Ein Vorteil ist, dass Sie die Anzahl der Zeilen in der Datei in NR
/ notieren FNR
.