Vim - Hinzufügen einer Leerzeile zwischen den Zeilen

15

Wie füge ich zwischen nicht leeren Zeilen eine Leerzeile ein?

z.B. von

line 1
line 2
line 3

line 4
line 5

zu

line 1

line 2

line 3

line 4

line 5
Ayutheos
quelle

Antworten:

27

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 E59Weitere 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 :gAnweisung 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.

Trevor Powell
quelle
1
Genau. Ich suche normalerweise nach Abkürzungen wie, :%norm oaber es stellt sich heraus, dass dies nicht wie beabsichtigt funktioniert o. +1
sehe
Geben Sie ein :%s/$/, drücken Sie und drücken Sie ^Vdann Enter.
Jpaugh
1
@jpaugh Angenommen, Sie meinen :%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.
Trevor Powell
3

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
Simon
quelle
Vielen Dank! Dies funktioniert und es werden keine weiteren Zeilen hinzugefügt, wenn ich die Suche erneut durchführe (wenn ich beispielsweise neue Zeilen in meine Datei aufgenommen habe).
1
Können Sie erklären, was die einzelnen regulären Ausdrücke im Suchmuster bedeuten? Wenn Sie sich vim help ansehen, \n\@<!\nbedeutet 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 :)
Ja, \n\@<!\nbedeutet 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
Simon
3

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\nLine2ergibt \1 = 1und \2 = L.

perreal
quelle
0

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!

Nick Gerrer
quelle
kbewegt sich eine Linie nach oben. jbewegt sich eine Linie hinunter.
Neil Forrester
Ja, in der Tat. Mein Fehler. Vielen Dank, Neil!
0
/[^\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
Neil Forrester
quelle
Meine Datei enthält viele Zeilen. Gibt es eine Möglichkeit, eine Regex-Suche durchzuführen und eine Leerzeile für die gesamte Datei einzufügen? Ich habe mir stackoverflow.com/questions/2673209/… angesehen , konnte aber nicht verstehen , was alle Regex-Befehle bedeuten.
In meinem obigen Abschnitt finden Sie eine alternative Möglichkeit, dasselbe mit einem einzigen Befehl und ohne rekursive Zuordnung zu erreichen. Der erste Weg sollte jedoch für die gesamte Datei funktionieren.
Neil Forrester
0

Versuchen Sie diesen Befehl ( 16Zeichen):

:%!sed G|cat -s
kev
quelle
Anstatt zu versuchen, einen kurzen Befehl zu "vimgolfen", wäre eine kleine Erklärung der eher undurchsichtigen verwendeten Optionen hilfreicher.
Ingo Karkat
0

Ich weiß nicht, wie lang Ihre Datei ist, aber eine der einfachsten Methoden ist die Eingabe oim Befehlsmodus. Und in der nächsten Zeile .. Dies kann in ein einfaches Makro geladen werden.

Demagoge
quelle