2017-04-30 4 views
1

Ich habe folgenden Text mit vielen Zeilen. Aufeinander folgende Zeilen sind Teil eines Absatzes. Aber Linien, die durch eine Leerzeile getrennt sind, sind Teil einzelner Absätze. folgender Text hat daher Linien für 2 Absätze:Zeilen zu Absätzen in Vim zusammenfügen

first group of lines. 
first group of lines. 
first group of lines. 
first group of lines. 
first group of lines. 
first group of lines. 

second group of lines. 
second group of lines. 
second group of lines. 
second group of lines. 
second group of lines. 
second group of lines. 

I folgenden Code bin mit aufeinanderfolgenden Zeilen in Absätze fusionieren:

%s/\n\n\@!//g 

Es folgende Konsequenzen haben:

first group of lines.first group of lines.first group of lines.first group of lines.first group of lines.first group of lines. 
second group of lines. second group of lines. second group of lines. second group of lines. second group of lines. second group of lines. 

Daher Absätze gebildet aber sie sind nicht durch eine Leerzeile getrennt. Wenn ich meinen Befehl erneut ausführen, werden diese auch in einem einzigen Absatz zusammengeführt. Wie kann ich meinen Code ändern, um eine Leerzeile zwischen neu gemacht Absätzen zu halten, so dass die Ausgabe wie folgt:

first group of lines.first group of lines.first group of lines.first group of lines.first group of lines.first group of lines. 

second group of lines. second group of lines. second group of lines. second group of lines. second group of lines. second group of lines. 

Vielen Dank für Ihre Hilfe.

Antwort

1
:%s/\([^\n]\)\n\([^\n]\)/\1\2/g 

erledigt die Arbeit.

Hier verwenden Sie Substitutionsgruppen. Sie suchen nach einem

  • non Zeilenvorschubzeichen (gedruckte später mit \ 1)
  • Zeilenvorschubzeichen (die später angegeben wird)
  • non Zeilenvorschubzeichen (gedruckte später mit \ 2)
+0

Einige Erklärungen, wie es funktioniert, werden hilfreich sein. Gibt es Situationen, die bei der Verwendung dieses Codes zu beachten sind? – rnso

+0

Natürlich. Hinzugefügt. –

+0

Eigentlich scheint mir derjenige, der von @yolenoyer gepostet wird, besser zu sein –

3

Dieser (ganz ähnlich wie Manuel Schmidt Antwort) funktioniert:

:%s/[^\n]\zs\n\ze[^\n]// 

Einige Erklärungen:

  • Was Aufenthalte zwischen \zs und \ze (a Wagenrücklauf \n)
  • [^\n] bedeutet entfernt werden: jede char aber einen Wagenrücklauf

So der Befehl bedeutet: bitte entfernen ein Wagenrücklauf, aber nur wenn es zwischen zwei Nicht-Wagenrücklauf-Zeichen ist

EDIT: Eine noch bessere Lösung aus melpomene:

:%s/.\zs\n\ze.// 
+1

Sie können '.' anstelle von' [^ \ n] 'verwenden. – melpomene

+0

@melpomene: '.' bedeutet alles. Warum wird die Leerzeile nicht entfernt, d. H. Ersetzen Sie "\ n \ nNext line" durch "\ nNext line"? – rnso

+0

Auch warum 'g' am Ende des Codes nicht benötigt wird? – rnso

1

dies bedenkt, ist eine vim Frage, hier ist eine vim Antwort (im Gegensatz zu einer RegEx Antwort entgegengesetzt).

Jeder Zeilenblock wird durch vim als Absatz gesehen, also von jedem Ort der Absatz, den Sie eingeben können:

vipgJ 

den Absatz wählt diese visuell (vip) und verbindet alle Linien ohne das Hinzufügen oder Entfernen Leerzeichen (gJ).

Hier ist eine Möglichkeit, einen Makro zu erstellen, die den aktuellen Absatz verbindet, bewegt sich dann zum nächsten, bereit, wieder laufen:

qqvipgJjjq 

nun das Makro mit @q laufen. Wenn Sie wissen, wie oft Sie es ausführen möchten, können Sie diese Nummer voranstellen [email protected], oder geben Sie einfach eine große Zahl ein, um es auf den Rest des Dokuments anzuwenden.

Für einen wirklich coolen Trick, können Sie sogar das Makro schreiben, um sich selbst rekursiv zu nennen. Es wird sich selbst so lange aufrufen, bis es keine Änderungen mehr vornimmt - in diesem Fall wenn es das Ende des Dokuments erreicht (vergewissere dich, dass dein q Register leer ist, bevor du damit beginnst, sonst wirst du das existierende Makro anwenden, während du das neue schreibst) klar kann es durch einfaches Eintippen qqq):

[email protected]@q 

Erläuterung:

  • qq: beginnen sie ein Makro in das Register "q" der Aufnahme.
  • vipgJ: verbinden Sie den aktuellen Absatz.
  • jj: Bewegen Sie sich 2 Zeilen zum nächsten Absatz.
  • @q run Makro "q" (tut nichts während der Aufnahme, seit Register "q" ist leer).
  • q: Stoppen Sie die Aufnahme des Makros.
  • @q: Führen Sie das Makro aus.
+0

Können Sie die Anzahl der Zeilen im Dokument zählen und diese Nummer verwenden? – rnso

+0

Sie arbeiten nicht mit Linien, Sie arbeiten mit Liniengruppen, so dass die Anzahl der Linien in der Datei nicht hilft. Und egal, es spielt keine Rolle - wenn Sie Ihre Änderungen auf die gesamte Datei anwenden möchten, führen Sie einfach das rekursive Makro oder das einfache Makro mit einer großen Anzahl wie '999 @ q' aus – nickspoon