Es ist wirklich ziemlich genial. Lassen Sie es uns brechen. Der ex
Befehl
g/^$/xyzzy
sucht nach allen leeren Zeilen und führt den xyzzy
Befehl (einen beliebigen ex
Befehl) für jede Zeile aus. Beachten Sie, dass dies xyzzy
kein echter ex
Befehl ist, sondern nur als Platzhalter, wie im nächsten Absatz beschrieben.
Das Knifflige dabei ist, dass der xyzzy
"Befehl" in Ihrem Fall noch ein weiterer Suchbefehl ist:
,/./-j
Der ,/./-
gibt einen Bereich an. Dies ist von der Form, <start>,<end>
und da vor dem Komma nichts steht, wird davon ausgegangen, dass die aktuelle Zeile (die, in der Sie die leere Zeile gefunden haben) der Anfang ist.
Nach dem Komma steht, /./-
was bedeutet, dass nach dem nächsten Zeichen gesucht wird ( .
bedeutet ein beliebiges Zeichen). Sichern Sie dann eine Zeile ( /./-
ist /./-1
eine Abkürzung, da diese impliziert wird, wenn kein Wert angegeben ist). Sie finden dieses Muster .
in der ersten nicht leeren Zeile nach dem Muster, mit dem Sie arbeiten.
Mit anderen Worten, das Ende des Bereichs ist die letzte leere Zeile nach oder an der Stelle, an der Sie gerade arbeiten.
Dann führen Sie einen Join über diesen Bereich aus.
Wenn der Anfang und das Ende des Bereichs gleich waren (nur eine leere Zeile befand sich im Abschnitt), führt der Join nichts aus. Wenn sie nicht gleich sind, fügt join sie alle zusammen.
Auf diese Weise werden mehrere Leerzeilen zu einer zusammengefasst.
Schauen wir uns ein Beispiel an (die Zeilennummern dienen nur zur Erklärung, sie befinden sich nicht in der eigentlichen Datei):
1 Line 1
2
3 Line 3
4 Line 4
5
6
7
8
9 Line 9
Der g/^$/
Befehl findet alle leeren Zeilen und bearbeitet sie (dies sind die Zeilen 2, 5, 6, 7 und 8).
Richtet für Zeile 2 ,/./-j
einen Bereich von 2 bis 2 ein (der nächste .
befindet sich in Zeile 3, subtrahiert dann 1, um 2 zu erhalten). Ein Join auf der Range 2,2 macht nichts.
Richtet für Zeile 5 ,/./-j
einen Bereich von 5 bis 8 ein (wird als nächstes .
in Zeile 9 gefunden und dann von 1 subtrahiert). Ein Join im Bereich 5,8 verbindet alle diese Zeilen miteinander.
Der Vorgang wird nicht für Zeilen ausgeführt, die als Teil eines früheren Vorgangs verschwinden. Das liegt daran, dass es keinen Sinn macht, Zeilen zu verarbeiten, die zu einem früheren Zeitpunkt im Zyklus gelöscht wurden.
Mit anderen Worten, da die Zeilen 6 bis 8 gelöscht werden (in Kombination mit Zeile 5), wird der globale Befehl danach nicht mehr auf sie angewendet.
Dies basiert auf der Tatsache, dass in der vim
Dokumentation ein Algorithmus mit zwei Durchläufen angegeben ist, einer zum Markieren der Zeilen und einer zum Ausführen der Operation.