So ersetzen Sie ein Zeichen in Vim durch eine neue Zeile

1967

Ich versuche, jede ,in der aktuellen Datei durch eine neue Zeile zu ersetzen :

:%s/,/\n/g 

Aber es fügt ein, was wie eine ^@statt einer tatsächlichen Newline aussieht. Die Datei befindet sich nicht im DOS-Modus oder so.

Was sollte ich tun?

Wenn Sie neugierig sind, wie ich, überprüfen Sie die Frage Warum ist \ ra Newline für Vim? auch.

Vinko Vrsalovic
quelle
2
Stack Overflow ist eine Site für Programmier- und Entwicklungsfragen. Diese Frage scheint nicht zum Thema zu gehören, da es nicht um Programmierung oder Entwicklung geht. Siehe Welche Themen kann ich hier in der Hilfe erfragen? Vielleicht ist Super User oder Unix & Linux Stack Exchange ein besserer Ort, um zu fragen.
JWW
5
@jww Diese Frage ist 10 Jahre alt ... scheint zu alt zu sein, um zu migrieren. Es gibt viele Fragen wie diese, zum Beispiel: stackoverflow.com/questions/10175812/…
Vinko Vrsalovic
14
@jww vim ist ein Tool, das häufig für Programmierer verwendet wird, und Fragen zu Tools, die häufig für Programmierer verwendet werden, werden im Stapelüberlauf behandelt . Obwohl dies offensichtlich besser für Vi und Vim geeignet ist .
user202729

Antworten:

2565

Verwenden Sie \ranstelle von \n.

Durch Ersetzen durch wird \nein Nullzeichen in den Text eingefügt. Verwenden Sie, um eine neue Zeile zu erhalten \r. Bei der Suche nach einer neuen Zeile würden Sie diese jedoch weiterhin verwenden \n. Diese Asymmetrie beruht auf der Tatsache, dass \nund \r etwas andere Dinge tun :

\nentspricht einem Zeilenende (Zeilenumbruch), während \rein Wagenrücklauf übereinstimmt. Auf der anderen Seite wird bei Ersetzungen \nein Nullzeichen \reingefügt, während eine neue Zeile eingefügt wird (genauer gesagt, sie wird als Eingabe behandelt <CR>). Hier ist ein kleines, nicht interaktives Beispiel, um dies mithilfe der Vim-Befehlszeilenfunktion zu veranschaulichen (mit anderen Worten, Sie können Folgendes kopieren und in ein Terminal einfügen, um es auszuführen). xxdzeigt einen Hexdump der resultierenden Datei.

echo bar > test
(echo 'Before:'; xxd test) > output.txt
vim test '+s/b/\n/' '+s/a/\r/' +wq
(echo 'After:'; xxd test) >> output.txt
more output.txt
Before:
0000000: 6261 720a                                bar.
After:
0000000: 000a 720a                                ..r.

Mit anderen Worten, \nhat das Byte 0x00 in den Text eingefügt; \rhat das Byte 0x0a eingefügt.

Konrad Rudolph
quelle
127
/ r wird als Drücken der Eingabetaste behandelt. Es funktioniert auf allen Plattformen.
Luka Marinko
73
Siehe auch Warum ist \ ra newline für Vim? .
Andrew Marshall
14
Ich wünschte, dies würde für klassische vi funktionieren. Funktioniert unter AIX v6.1 \rnicht so. Aber Sie können Ctrl-V Enteranstelle der Eingabe drücken \r, und es funktioniert.
eksortso
3
Ich bin zu spät zur Party. Wenn ich eine Null \reinfüge <CR>und \neinfüge, wie würde ich etwas durch einen Wagenrücklauf ersetzen?
Mr. Llama
2
@ SunnyRaj sind Sie sicher über die Geschichte von CR und LF? Ich hatte den Eindruck, dass ursprünglich LF Papier eine Reihe vorwärts bewegte, aber den Druckkopf nicht bewegte, und CR den Druckkopf bewegte, aber das Papier nicht bewegte. Wenn Ihr Betriebssystem die Eingabe vor dem Drucken nicht konvertiert hat, können Sie daher nicht nur LF oder CR verwenden, um die richtige Ausgabe zu erhalten. MS DOS verwendete Rohdruckerdaten als Textdateiformat, Mac OS verwendete CR und konvertierte von diesem in das Rohformat des Druckers und UNIX verwendete LF und konvertierte von diesem in das Rohformat des Druckers.
Mikko Rantalainen
210

Hier ist der Trick:

Stellen Sie zunächst Ihre Vi (m) -Sitzung so ein, dass der Musterabgleich mit Sonderzeichen (z. B. Zeilenumbruch) möglich ist. Es lohnt sich wahrscheinlich, diese Zeile in Ihre .vimrc- oder .exrc-Datei einzufügen:

:set magic

Als nächstes machen Sie:

:s/,/,^M/g

Um den ^MCharakter zu erhalten, tippe Ctrl+ Vund drücke Enter. Machen Sie unter Windows Ctrl+Q , Enter. Ich kann mich nur daran erinnern, wie wenig Sinn sie machen:

A: Was wäre das schlechteste Steuerzeichen, um eine neue Zeile darzustellen?

B: Entweder q(weil es normalerweise "Beenden" bedeutet) oder vweil es so einfach wäre, versehentlich Ctrl+ Ceinzugeben und den Editor zu beenden .

A: Mach es so.

Logan
quelle
9
Ich verwende GVim unter Windows und brauche weder das :set magic(es ist auch nicht in meinem ~ / _vimrc) noch ctrl-q. Nur eine einfache ctrl-vgefolgt von Eingabe schafft den ^MCharakter für mich ganz gut.
Chris Phillips
5
Lebenslauf stellt keine neue Zeile dar; Dies ist der Befehl "Escape Next Literal Character". Ich weiß auch nicht, wofür Cv eine Mnemonik ist, aber es gibt einen Grund, warum es mental nicht auf Newline abgebildet wird.
Jim Stewart
27
Strg-v ist eine Mnemonik für "wörtlich" - dh Escape-Next-Taste, die auf ihren "wörtlichen" Schlüsselcode / Zeichen gedrückt wird. In Windows ist es Einfügen: um die Dinge vertraut zu halten. Strg-Q steht vielleicht für "(un) Quote". Jedenfalls ziemlich dumm - aber Sie können es in Binärdateien verwenden - z. B. um nach Strg-A bis Strg-Z zu suchen (Ascii 1-26, denke ich).
Tomasz Gandor
1
Ctrl-Cbeendet den Editor nicht wirklich, obwohl Sie dadurch wieder in den normalen Modus zurückkehren können. Ctrl-Vbedeutet wörtlich und Ctrl-Qbedeutet, dass jemand den Fehler gemacht hat, die $VIMRUNTIME/mswin.vimKonfigurationsdatei zu laden . Sie brauchen keine mswin. Verwenden Sie stattdessen einfach Ihr eigenes vimrc.
00dani
Wow das ist beeindruckend. Ich habe es sed -n l bis jetzt gemacht. Gut zu wissen, dass das gleiche mit Ctrl-vin vim erreicht werden kann.
Arpit
98

In der Syntax s/foo/bar, \rund \nunterschiedliche Bedeutungen haben, je nach Kontext.


Kurz:

Für foo:

\ n = Newline (LF unter Linux / Mac, CR + LF unter Windows)
\ r = Wagenrücklauf (CR)

Für bar:

\ r = ist Zeilenumbruch
\ n = Null-Byte.

Länger (mit ASCII-Nummern):

NUL= 0x00 = 0 = Ctrl+ @
LF= 0x0A = 10 = Ctrl+ J
CR= 0x0D = 13 = Ctrl+M

Hier ist eine Liste der ASCII-Steuerzeichen . Fügen Sie sie über Ctrl+ V, Ctrl+ in Vim ein ---key---.

Geben Sie in Bash oder den anderen Unix / Linux-Shells einfach Ctrl+ ein---key--- .

Versuchen Sie Ctrl+ Min Bash. Es ist dasselbe wie Schlagen Enter, da die Shell erkennt, was gemeint ist, obwohl Linux-Systeme Zeilenvorschübe zur Zeilenbegrenzung verwenden.

Um Literale in Bash einzufügen, funktioniert es auch , wenn Sie ihnen Ctrl+ voranstellen V.

Versuchen Sie es in Bash:

echo ^[[33;1mcolored.^[[0mnot colored.

Dies verwendet ANSI-Escape-Sequenzen . Fügen Sie die beiden ^[über Ctrl+ V, Esc.

Sie können auch versuchen, Ctrl+ V, Ctrl+M , Enter, die Sie dies:

bash: $'\r': command not found

Erinnere dich an die \r du von oben? :>

Diese Liste der ASCII-Steuerzeichen unterscheidet sich von einer vollständigen ASCII-Symboltabelle darin , dass die Steuerzeichen, die über die in eine Konsole / Pseudoterminal / Vim eingefügt werdenCtrl Schlüssel (haha) werden.

Während in C und den meisten anderen Sprachen normalerweise die Oktalcodes verwendet werden, um diese 'Zeichen' darzustellen.

Wenn Sie wirklich wissen wollen, woher das alles kommt: Der TTY entmystifiziert . Dies ist der beste Link, den Sie zu diesem Thema finden, aber Vorsicht: Es gibt Drachen.


TL; DR

Normalerweise foo= \nund bar= \r.

sjas
quelle
1
Ich bin fasziniert, wie Sie einen Charakter durch einen Wagenrücklauf
ersetzen
2
@codeshot :s/x/^M/gsollte reichen. Fügen Sie die ^MVia ctrl-vgefolgt von ein ctrl-m.
Sjas
3
Danke sjas, du weißt, diese Frage ist eine der seltsamsten aller Zeiten. 1008 Stimmen für die Antwort, die im Grunde nichts anderes sagt als "vim macht das, was Sie gefunden haben. Das liegt daran, dass vim das macht, was Sie gefunden haben. Vergessen Sie niemals, dass vim das macht, was Sie gefunden haben." Ich hatte gehofft, eine Auswahlliste mit Codes für interessante Zeichen im Muster, den Ersatz und den Grund für die Verrücktheit zu finden, damit man sich leicht an andere ähnliche Verrücktheiten erinnern und diese vorhersagen kann. Das hätte meine Stimme bekommen.
Codeshot
@codeshot Eine Liste von ASCII-Steuerzeichen könnte Ihnen helfen. Weitere Informationen finden Sie unter cs.tut.fi/~jkorpela/chars/c0.html . Ich werde meine Antwort so aktualisieren, dass sie zwei Links enthält.
Sjas
55

Sie müssen verwenden:

:%s/,/^M/g

Um den ^MCharakter zu erhalten, drücken Sie Ctrl+ vgefolgt von Enter.

Dogbane
quelle
4
Ich muss <Cv> <Cm> ausführen, um das Zeichen ^ M zu erhalten.
Jezen Thomas
39

\r kann die Arbeit hier für Sie erledigen.

Lasar
quelle
24

Verwenden Sie unter Vim unter Windows Ctrl+ Qanstelle von Ctrl+ V.

grantc
quelle
16

Dies ist die beste Antwort für die Art und Weise, wie ich denke, aber in einer Tabelle wäre es schöner gewesen:

Warum ist \ ra Newline für Vim?

Also, umformulieren:

Sie müssen verwenden \r, um einen Zeilenvorschub (ASCII 0x0A, die Unix-Newline) in einem Regex-Ersatz zu verwenden, aber das ist dem Ersatz eigen - Sie sollten normalerweise weiterhin damit rechnen, ihn \nfür den Zeilenvorschub und \rfür den Wagenrücklauf zu verwenden.

Dies liegt daran, dass Vim \nin einem Ersatz das NIL-Zeichen (ASCII 0x00) bezeichnet. Sie haben vielleicht erwartet, dass NIL \0stattdessen \nfür die übliche Verwendung für Zeilenvorschub \0freigegeben wurde , hat aber bereits eine Bedeutung für Regex-Ersetzungen, sodass es auf verschoben wurde \n. Gehen Sie daher weiter, um auch die neue Zeile von \nnach zu verschieben \r(was in einem Regex-Muster das Wagenrücklaufzeichen ASCII ist 0x0D).

Zeichen | ASCII-Code | C Darstellung | Regex-Übereinstimmung | Regex-Ersatz
------------------------- + ------------ + ----------- ------- + ------------- + ------------------------
nil | 0x00 | \ 0 | \ 0 | \ n
Zeilenvorschub (Unix-Zeilenumbruch) | 0x0a | \ n | \ n | \ r
Wagenrücklauf | 0x0d | \ r | \ r | <unbekannt>

NB: ^M( Ctrl+ V Ctrl+ Munter Linux) fügt eine neue Zeile ein, wenn sie in einem regulären Ausdruck anstelle eines Wagenrücklaufs verwendet wird, wie andere empfohlen haben (ich habe es gerade versucht).

Beachten Sie auch, dass Vim das Zeilenvorschubzeichen beim Speichern in eine Datei basierend auf den Dateiformateinstellungen übersetzt. Dies kann zu Verwirrung führen.

Codeshot
quelle
11

In Eclipse können die ^MZeichen in eine Zeile eingebettet werden, und Sie möchten sie in Zeilenumbrüche konvertieren.

:s/\r/\r/g
Rickfoosusa
quelle
8

Aber wenn man ersetzen muss, dann funktioniert folgendes:

:%s/\n/\r\|\-\r/g

Oben wird jede nächste Zeile durch die nächste Zeile und dann immer |-wieder durch eine neue Zeile ersetzt. Dies wird in Wiki-Tabellen verwendet.

Wenn der Text wie folgt lautet:

line1
line2
line3

Es wird geändert in

line1
|-
line2
|-
line3
Kiran K Telukunta
quelle
7

Wenn Sie es für eine ganze Datei tun müssen, wurde mir auch vorgeschlagen, dass Sie es über die Befehlszeile versuchen könnten:

sed 's/\\n/\n/g' file > newfile
Evan Donovan
quelle
1
Beachten Sie, dass dies GNU sed erfordert. Versuchen Sie printf 'foo\\nbar\n' | sed 's/\\n/\n/g'zu sehen, ob es auf Ihrem System funktioniert. (Dank an die guten Leute von #bash on freenode für diesen Vorschlag.)
Evan Donovan
Ja, aber die Frage betraf Vim. Es gibt eine Frage zum Stapelüberlauf. Wie kann ich eine neue Zeile (\ n) mit sed ersetzen? .
Peter Mortensen
5

Hier ist die Antwort, die für mich funktioniert hat. Von diesem Typ:

---- Zitieren Verwenden Sie den vi-Editor, um ein Zeilenumbruchzeichen in replace einzufügen


Etwas anderes muss ich tun und kann mich nicht erinnern und muss dann nachschlagen.

Gehen Sie in vi wie folgt vor, um ein Zeilenumbruchzeichen in eine Suche einzufügen und zu ersetzen:

:%s/look_for/replace_with^M/g

Der obige Befehl würde alle Instanzen von "look_for" durch "replace_with \ n" ersetzen (wobei \ n "newline" bedeutet).

Um das "^ M" zu erhalten, geben Sie die Tastenkombination Ctrl+ ein Vund drücken Sie danach (lassen Sie alle Tasten los) die EnterTaste.


Peter Mortensen
quelle