Czy zduplikowane linie zaczynają się od „x”, zastępując „x” w duplikacie „y”?

9

Mam plik o następującym wzorze:

foo 111
baz
foo 222
baz
foo 333
baz

w który należy przekształcić

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

Powiel więc wszystkie linie zaczynające się od fooi zmieniaj tylko foow duplikacie, ale resztę linii (która różni się w każdym przypadku) pozostaje nienaruszona. Jak to zrobić?

LB7979
źródło
Jeśli nie jesteś związany piekłem po wyrażeniu regularnym, makro będzie w porządku. Tak naprawdę nie ma to większego znaczenia w takich prostych przypadkach, ale jeśli masz coś bardziej skomplikowanego, jest to bardzo ważna alternatywa.
PhilippFrank

Odpowiedzi:

19

Proszę bardzo:

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

Rozkład:

: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'

Ponieważ gpolecenie zaktualizuje wzorzec wyszukiwania, więc można pominąć wzorzec, który ma zostać zastąpiony w poleceniu zastępczym. (odniesienie: :h :gwyszukaj search pattern).


Starsza wersja:

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

Rozkład:

: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

Aby włożyć ^Mprasę Ctrl+vi enter.

Uwaga : oryginalnie wymyśliłem „starszą” wersję, zanim dowiedziałem się o tpoleceniu. Zostawię to, ale nie polecam jej używać. Pierwszy jest bardziej przejrzysty i prosty.

nobe4
źródło
Rozwiązany „prostsza wersja” działała idealnie. W pierwszej wersji zduplikowana linia wciąż zaczyna się od foo...
LB7979
dziwne, wszedłeś tak, ^Mjak wyjaśniłem?
nobe4 14.04.16
Mój zły, nie czytałem zbyt dobrze. Pierwsze rozwiązanie również działa!
LB7979
Nie wiem, dlaczego w ogóle zawracasz sobie głowę skomplikowaną wersją. Prostsza wersja jest ... prostsza. ;) (Nie wspominając o zgodności z POSIX.) Dlaczego nie postawić go na pierwszym miejscu?
Wildcard
1
Początkowo wymyśliłem pierwszą wersję, która była dla mnie bardziej naturalna, ponieważ wtedy nie byłem tego świadomy t, a potem dodałem drugą. Zmienię kolejność, masz rację. A może pierwszym z nich jest POSIX?
nobe4
1

Robię takie rzeczy przez cały czas i po prostu robię coś podobnego %s/^foo \(.*\)/foo \1\rbar \1/(częściowo dlatego, że wykonuję wiele podobnych zadań, których nie można przekształcić w coś sprytnego za pomocą funkcji kopiowania i \(.*\)jest to teraz część mojej pamięci mięśniowej).

Podejrzewam, że nie jest zgodny z POSIX (nie działa na innych klonach vi), ale użycie ^M( C-VReturn) zamiast \rwydaje się działać na większości innych klonów vi.

Losowo 832
źródło