Wie funktioniert: g /^$/,/./- j (mehrere Leerzeilen auf ein Leerzeichen reduzieren) in vim?


21

In dem Artikel Vim Regular Expressions gibt Oleg Raisky den folgenden Befehl aus, um mehrere Leerzeilen auf ein einzelnes Leerzeichen zu reduzieren:

:g/^$/,/./-j

Kann jemand bitte beschreiben, wie das funktioniert?

Ich kenne :gBefehle und reguläre Ausdrücke. Aber ich habe nicht verstanden, was der Teil /,/./-jmacht.

Antworten:


24

Es ist wirklich ziemlich genial. Lassen Sie es uns brechen. Der exBefehl

g/^$/xyzzy

sucht nach allen leeren Zeilen und führt den xyzzyBefehl (einen beliebigen exBefehl) für jede Zeile aus. Beachten Sie, dass dies xyzzykein 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 /./-1eine 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 ,/./-jeinen 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 ,/./-jeinen 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 vimDokumentation ein Algorithmus mit zwei Durchläufen angegeben ist, einer zum Markieren der Zeilen und einer zum Ausführen der Operation.


2
Beachten Sie, dass sich dieser Befehl beschwert, wenn Sie am Ende Ihrer Datei Leerzeilen haben.
Wildcard
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.