Замените n-е вхождение слова в vim

Я видел другие вопросы, связанные с нахождением n-го вхождения слова/шаблона, но я не мог найти, как вы на самом деле замените n-е вхождение шаблона в vim. Там очевидный способ жесткого кодирования всех вхождений, таких как

:s/.*\(word\).*\(word\).*\(word\).*/.*\1.*\2.*newWord.*/g 

Есть ли лучший способ сделать это?

Ответы

Ответ 1

Вы можете сделать это немного проще, используя несколько поисков. Пустой шаблон в команде :s/pattern/repl/ означает замену последнего результата поиска.

:/word//word//word/ s//newWord/
or
:/word//word/ s/word/newWord/

Затем вы можете повторить это несколько раз, выполнив @: или даже [email protected]:, чтобы повторить команду еще 10 раз.

В качестве альтернативы, если бы я делал это в интерактивном режиме, я бы сделал что-то вроде:

3/word
:s//newWord/r

Это найдет третье вхождение слова, начинающегося с курсора, а затем выполнит замену.

Ответ 2

Для информации

s/\%(\(pattern\).\{-}\)\{41}\zs\1/2/

также работает, чтобы заменить 42-е место. Тем не менее, я предпочитаю решение, данное Джоном Кугельманом, которое более просто - даже если оно не будет ограничиваться текущей строкой.

Ответ 3

Замените каждое N th появление PATTERN в строке с REPLACE.

:%s/\(\zsPATTERN.\{-}\)\{N}/REPLACE/

Ответ 4

Это отвечает на ваш реальный вопрос, но не ваши намерения.

Вы спросили о замене n-го вхождения слова (но, казалось, означали "внутри строки" ). Вот ответ на вопрос, как задавали, если кто-то найдет его, как я сделал =)

Для странных задач (например, для замены каждого 12-го появления "собака" на "попугай" ) мне нравится использовать рекурсивные записи.

Сначала запишите запись в @q

qqq

Теперь запустите новую запись в q

qq

Затем вручную сделайте то, что вы хотите сделать (используя пример выше, замените 12-е появление "собаки" на "попугай" ):

/dog
nnnnnnnnnnn

удалить "собаку" и войти в нее

diwi

тип попугая

parrot

Теперь воспроизводите текущую пустую запись "@q"

@q

который ничего не делает.

Наконец, прекратите запись:

q

Теперь ваша запись в @q вызывает себя в конце. Но поскольку он вызывает запись по имени, он больше не будет пустым. Итак, вызовите запись:

@q

Он воспроизведет запись, а затем, в конце, как последний шаг, снова воспроизведет. Он будет повторять это до конца файла.

TL;DR;

qq
q
/dog
nnnnnnnnnnndiwiparrot<esc>
@q
q
@q

Ответ 5

Хорошо, если вы сделаете /gc, тогда вы можете подсчитать количество раз, когда он просит вас подтвердить, и продолжите замену, когда вы доберетесь до n-го: D