Suchen und ersetzen Sie in vim in bestimmten Zeilen

91

ich kann nutzen

:5,12s/foo/bar/g

fooum es barzwischen den Zeilen 5 und 12 zu suchen und zu ersetzen . Wie kann ich das nur in Zeile 5 und 12 tun (und nicht in den Zeilen dazwischen)?

pfnuesel
quelle

Antworten:

72

Vim hat spezielle Atome mit regulären Ausdrücken, die in bestimmten Zeilen, Spalten usw.; Sie können sie (möglicherweise zusätzlich zum Bereich) verwenden, um die Übereinstimmungen zu begrenzen:

:5,12s/\(\%5l\|\%12l\)foo/bar/g

Sehen :help /\%l

Ingo Karkat
quelle
8
Ein komplizierterer Weg als ich erwartet hatte, aber meine Frage perfekt beantwortet. Vielen Dank!
Pfnuesel
55

Sie können die Ersetzung in Zeile 5 durchführen und in Zeile 12 mit minimalem Aufwand wiederholen:

:5s/foo/bar
:12&

Vergisst, wie Ingo :&betont hat, Ihre Flaggen. Da Sie verwenden /g, wäre der richtige Befehl :&&:

:5s/foo/bar/g
:12&&

Sehen :help :&und Freunde.

romainl
quelle
10
+1 für die :&Verwendung des Obskuren . Wenn es Flags ( s/../../g) gibt, muss man :&&allerdings ...
Ingo Karkat
10
@IngoKarkat, um fair zu sein, denke ich \(\%5l\|\%12l\)ist dunkler als:&
doubleDown
13

Sie können immer ein cam Ende hinzufügen . Dies wird für jedes Spiel eine Bestätigung verlangen.

:5,12s/foo/bar/gc
Dean
quelle
1
Dies kann ein Albtraum sein, wenn zwischen den Zeilen 5 und 12 viele Übereinstimmungen liegen (denken Sie daran, dass eine gFlagge im Spiel ist)
doubleDown
1
@doubleDown Dies ist keine universelle Lösung (wo es viele mögliche Kandidaten gibt), aber in den meisten Fällen ist es wirklich lästiger, n5 oder 6 Mal zu drücken, als \(\%5l\|\%12l\)die Ersatzanweisung hinzuzufügen ?
Dean
Ich finde das nützlich, ich wollte jede andere Zeile ändern, das wäre schneller gewesen als das, was ich letztendlich getan habe.
Tiktak
8

Interessante Frage. Es scheint, als gäbe es nur eine Bereichsauswahl und keine Mehrzeilenauswahl:

http://vim.wikia.com/wiki/Ranges

Wenn Sie jedoch in Zeile 5 und 12 etwas Besonderes haben, können Sie den :gOperator verwenden. Wenn Ihre Datei so aussieht (Zahlen nur als Referenz):

 1     line one
 2     line one
 3     line one
 4     line one
 5     enil one
 6     line one
 7     line one
 8     line one
 9     line one
10     line one
11     line one
12     enil one

Und Sie wollen ersetzen onedurch enoauf den Linien , wo es enilstatt line:

:g/enil/s/one/eno/
eckes
quelle
5
Dies setzt tatsächlich viel
voraus
1

Sie könnten edeinen zeilenorientierten Texteditor mit ähnlichen Befehlen wie vi und vim verwenden. Es ist wahrscheinlich älter als vi und vim.

In einem Skript (unter Verwendung eines Here-Dokuments, das Eingaben bis zur EndCommand-Markierung verarbeitet) würde es folgendermaßen aussehen:

ed file <<EndCommands
    5
    s/foo/bar/g
    7
    s/foo/bar/g
    wq
EndCommands

Natürlich können die ed-Befehle auch in der Befehlszeile verwendet werden.

Verdächtiger
quelle
3
Ich sehe keinen Vorteil gegenüber der vimAlternative.
Bernhard
1
Und das Gleiche kann auch mit Vim gemacht werden. Die Zahlen können tatsächlich vor das gesetzt werden :s, aber es gibt immer noch die Duplizierung des :sBefehls (was Romainls Lösung vermeidet).
Ingo Karkat
Meiner Ansicht nach wollte der Benutzer möglicherweise mehr als zwei Zeilen zum Bearbeiten auswählen. In diesem Fall könnte ein nicht interaktiver Ansatz von Interesse gewesen sein - was AFAIK mit vim nicht möglich ist.
Verdächtiger
1
Oh, Vim kann das (z. B. im "Ex" -Modus), aber Sie haben Recht, dass ein anderes Tool einem interaktiven Editor vorgezogen werden sollte. Meine Präferenz wäre jedoch sed...
Ingo Karkat