Doppelte Zeilen, die mit "x" beginnen und "x" im Duplikat durch "y" ersetzen?

9

Ich habe eine Datei mit folgendem Muster:

foo 111
baz
foo 222
baz
foo 333
baz

was in verwandelt werden muss

foo 111
bar 111
baz
foo 222
bar 222
baz
foo 333
bar 333
baz

Duplizieren Sie also alle Zeilen, die mit beginnen foo, und ändern Sie nur foodas Duplikat, lassen Sie jedoch den Rest der Zeile (der sich jeweils unterscheidet) intakt. Wie macht man das?

LB7979
quelle
Wenn Sie nicht an einen regulären Ausdruck gebunden sind, reicht ein Makro aus. In solchen einfachen Fällen ist das nicht wirklich wichtig, aber wenn Sie etwas Komplizierteres haben, ist es eine sehr gültige Alternative.
PhilippFrank

Antworten:

19

Bitte schön:

:g/foo/t.|s//bar

Zerlegen:

:g/foo/    " start a global command applied on all lines matching 'foo'
t.         " duplicate the current line (the cursor is now on the new line)
|          " chain a new command
s//bar     " substitute the last searched element with 'bar'

Da der gBefehl das Suchmuster aktualisiert, können Sie das zu ersetzende Muster im Ersatzbefehl weglassen. (ref : :h :g, suchen nach search pattern).


Ältere Version:

:g/foo/norm! yyp:s/foo/bar^M

Zerlegen:

:g            start a global command
/foo/         apply only on lines having 'foo'
norm!         execute a normal command
yyp           duplicate the line
:s//bar       replace foo with bar on the line (the duplicated one)
^M            add enter to execute the substitution

Zum Einsetzen der ^MPresse Ctrl+vund enter.

Hinweis : Ich habe mir ursprünglich die "ältere" Version ausgedacht, bevor ich von dem tBefehl erfahren habe . Ich werde es verlassen, aber ich werde es nicht empfehlen. Der erste ist sauberer und unkomplizierter.

nobe4
quelle
Gelöst funktionierte die 'einfachere Version' perfekt. Die erste Version führte jedoch dazu, dass die doppelte Zeile immer noch mit foo... begann
LB7979
seltsam, bist du eingetreten, ^Mwie ich erklärt habe?
nobe4
Mein schlechtes, nicht so gut gelesen. Die erste Lösung funktioniert auch!
LB7979
Ich weiß nicht, warum Sie sich überhaupt die Mühe machen, die komplizierte Version aufzunehmen. Die einfachere Version ist ... einfacher. ;) (Ganz zu schweigen von der POSIX-Konformität.) Warum nicht an erster Stelle?
Wildcard
1
Anfangs habe ich mir die erste Version ausgedacht, die für mich natürlicher war, weil ich es damals nicht wusste t, und dann habe ich die zweite hinzugefügt. Ich werde die Reihenfolge ändern, du hast recht. Wie wäre es mit dem ersten POSIX?
nobe4
1

Ich mache die ganze Zeit solche Sachen und mache einfach so etwas %s/^foo \(.*\)/foo \1\rbar \1/(teilweise, weil ich auch viele ähnliche Aufgaben mache, die mit einer Kopierfunktion nicht in etwas Kluges verwandelt werden können und \(.*\)mittlerweile Teil meines Muskelgedächtnisses sind).

Ich vermute, dass es nicht POSIX-kompatibel ist (es funktioniert nicht auf anderen vi-Klonen), aber die Verwendung von ^M( C-VReturn) anstelle von \rscheint auf den meisten anderen vi-Klonen zu funktionieren.

Random832
quelle