Повторяющиеся строки, начинающиеся с «x», заменяя «x» в дубликате на «y»?

9

У меня есть файл со следующим рисунком:

foo 111
baz
foo 222
baz
foo 333
baz

который должен быть превращен в

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

Итак, продублируйте все строки, начинающиеся с foo, и измените только fooдубликаты, но оставьте остальную часть строки (которая отличается в каждом случае) нетронутой. Как это сделать?

LB7979
источник
Если вы не одержимы регулярным выражением, макрос подойдет. В простых случаях, подобных этому, не имеет большого значения, но если у вас есть что-то более сложное, это очень верная альтернатива.
PhilippFrank

Ответы:

19

Ну вот:

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

Разбивая:

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

Поскольку gкоманда обновит шаблон поиска, вы можете пропустить шаблон для замены в команде замены. (ссылка:, :h :gпоиск search pattern).


Старая версия:

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

Разбивая:

: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

Чтобы вставить ^Mпресс Ctrl+vи enter.

Примечание : я изначально придумал «более старую» версию, прежде чем я узнал о tкоманде. Я оставлю это, но я не рекомендую использовать это. Первый чище, более простой.

nobe4
источник
Решено, «более простая версия» работала отлично. Однако первая версия привела к тому, что повторяющаяся строка все еще начиналась с foo....
LB7979
странно, ты вошел, ^Mкак я объяснил?
nobe4
Плохо, плохо читал. Первое решение работает также!
LB7979
Я не знаю, зачем вам вообще включать сложную версию. Более простая версия ... проще. ;) (Не говоря уже о совместимости с POSIX.) Почему бы не поставить его на первое место?
Wildcard
1
Первоначально я придумал первую версию, которая была более естественной для меня, потому что в то время я не знал об этом t, а затем я добавил вторую. Я поменяю порядок, вы правы. Как насчет первого из них POSIX?
nobe4
1

Я делаю подобные вещи все время и просто делаю что-то вроде этого %s/^foo \(.*\)/foo \1\rbar \1/(частично потому, что я также выполняю много похожих задач, которые невозможно превратить в нечто умное с помощью функции копирования, и на данный момент \(.*\)это часть моей мышечной памяти).

Я подозреваю, что это не POSIX-совместимый (он не работает на других клонах vi), но использование ^M( C-VReturn) вместо, \rкажется, работает на большинстве других клонов vi.

Random832
источник