Antworten:
Der Befehl: g von Vim wurde für genau diese Art von Aufgabe entwickelt. Ausführen einer einzelnen Aktion in jeder Zeile, die einem bestimmten Muster entspricht. Hier ist meine Antwort:
:g/.\n\n\@!/norm o
Das Muster, das ich benutze, ist /.\n\n\@!/
. Zerlegen Sie das in seine Einzelteile:
.
Entspricht einem beliebigen Zeichen in der Zeile. (wird verwendet, um vorhandene Leerzeilen sofort aus der Überlegung zu streichen)\n
Entspricht einem einzelnen \ n am Ende des obigen Zeichens\n\@!
Schlägt fehl, wenn unmittelbar nach dem vorherigen ein anderes \ n vorhanden ist.( :h E59
Weitere Informationen zu \@!
und ähnlichen Übereinstimmungsspezifizierern in regulären Ausdrücken - es gibt auch einige andere!)
Der reguläre Ausdruck des Befehls: g hat nun jede nicht leere Zeile ausgewählt, die durch eine einzelne neue Zeile abgeschlossen wird und auf die keine leere Zeile folgt.
Nach dem Muster in einer :g
Anweisung folgt der Befehl zum Ausführen in übereinstimmenden Zeilen. In diesem Fall habe ich es angewiesen, einen normalen Modus-Befehl (abgekürzt als norm
) auszuführen , und der auszuführende Befehl lautet einfach o
, wobei eine leere Zeile unter der aktuellen Zeile eingefügt wird.
Zusammengefasst findet der Befehl jede Zeile, die keine Leerzeile enthält, und fügt eine hinzu. Und das ist alles was dazu gehört! Vielleicht möchten Sie im Power of G- Artikel des Vim-Wikis nach weiteren interessanten Dingen suchen :g
(und nach der negativen Schwester :v
). Dies ist einer der erstaunlich nützlichen Befehle, auf die Sie sich bald verlassen und die Sie in den Editoren fürchterlich vermissen die haben es nicht.
:%s/$/
, drücken Sie und drücken Sie ^V
dann Enter
.
:%s/$/<C-V><CR><CR>
(um die übliche Vim-Folk-Codierung von Tastendrücken zu verwenden), fügt dieser Ansatz nach jeder Zeile eine neue Zeile hinzu. Das heißt, Zeilen, die bereits durch Leerzeichen getrennt sind (siehe Zeile 3 -> Zeile 4 im Beispieltext), erhalten zusätzliche Leerzeilen. Die ursprüngliche Frage bestand darin, das Hinzufügen zusätzlicher Leerzeilen zu vermeiden, wenn diese bereits im Ausgangstext vorhanden waren.
Beim Testen von @ NeilForesters globaler Such- und Ersetzungsantwort stellte ich fest, dass jede zweite vorgesehene Ersetzung in aufeinanderfolgenden nicht leeren Zeilen übersehen wurde, wenn die Zeilen jeweils nur ein Zeichen enthielten. Dies scheint darauf zurückzuführen zu sein, dass das Muster bei jeder Gelegenheit nach dem letzten Zeichen übereinstimmt, mit dem es bei der vorherigen Gelegenheit übereinstimmt.
Die Verwendung von lookbehind und lookahead löst dieses Problem und verkürzt auch die Regex:
:%s/\n\@<!\n\n\@!/\r\r/g
\n\@<!\n
bedeutet dies, dass ein Zeilenumbruch, der nach einem anderen Zeilenumbruch nicht richtig ist, richtig ist? Aber ich konnte nicht verstehen, was das \n\@!
bedeutet. Ich würde es gerne verstehen, damit ich es lernen und auf andere Suchmuster anwenden kann :)
\n\@<!\n
bedeutet einen Zeilenumbruch, der nicht unmittelbar auf einen anderen Zeilenumbruch folgt. \n\@!
Stimmt mit der Breite Null überein, wenn das vorhergehende Atom (dh \n
) nicht unmittelbar vor dem folgenden übereinstimmt. Versuchen Sie :help \@<!
, die Dokumentation dazu in vim zu sehen. I
Ein anderer Weg:
%s/\(.\)\n\(.\)/\1\r\r\2/
Was bedeutet,
\(.\) match and capture a non-newline character,
\n match a newline
\(.\) match and capture a non-newline character
Ersetzen durch: Erstes Capture, doppelte Zeilenumbrüche und das zweite Capture.
Zum Beispiel line1\nLine2
ergibt \1 = 1
und \2 = L
.
Korrigiere mich, wenn ich falsch liege. Ich glaube, Sie verwenden den Buchstaben k im Befehlsmodus, um eine Zeile nach unten zu bewegen. Rufen Sie dann den Einfügemodus auf und fügen Sie die nächste Zeile hinzu. Bei Bedarf wiederholen? Hoffe das hilft!
k
bewegt sich eine Linie nach oben. j
bewegt sich eine Linie hinunter.
/[^\n]\n[^\n]
:map <F2> no<esc><F2>
Dann drücken Sie <F2>
. Dadurch werden zwei aufeinanderfolgende nicht leere Zeilen gesucht und dann wiederholt eine Zeile dazwischen eingefügt.
Bearbeiten:
Hier ist eine alternative Möglichkeit, dies mit einem einzigen globalen Suchen und Ersetzen zu tun:
:%s/\([^\n]\)\n\([^\n]\)/\1\r\r\2/g
Versuchen Sie diesen Befehl ( 16
Zeichen):
:%!sed G|cat -s
:%norm o
aber es stellt sich heraus, dass dies nicht wie beabsichtigt funktionierto
. +1