Искать и заменять в vim в определенных строках


95

я могу использовать

:5,12s/foo/bar/g

найти fooи заменить его barмежду строками 5 и 12. Как я могу сделать это только в строках 5 и 12 (а не в строках между ними)?

Ответы:


76

В Vim есть специальные атомы регулярных выражений, которые соответствуют определенным строкам, столбцам и т. Д .; вы можете использовать их (возможно, в дополнение к диапазону) для ограничения совпадений:

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

Увидеть :help /\%l


8
Более сложный способ, чем я ожидал, но отлично отвечает на мой вопрос. Благодарность!
pfnuesel

56

Вы можете выполнить замену в строке 5 и повторить ее с минимальными усилиями в строке 12:

:5s/foo/bar
:12&

Как указал Инго, :&забывает ваши флаги. Поскольку вы используете /g, правильная команда будет :&&:

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

Смотрите :help :&и друзья.


10
+1 за использование неясного :&. Если есть flags ( s/../../g), нужно использовать :&&, хотя ...
Инго Каркат

10
@IngoKarkat, если честно, я думаю, что \(\%5l\|\%12l\)это более неясно, чем:&
doubleDown

13

Вы всегда можете добавить cв конец. Это будет запрашивать подтверждение для каждого матча.

:5,12s/foo/bar/gc

1
Это может стать кошмаром, если между строками 5 и 12 много совпадений (имейте в виду, что в игре есть gфлаг)
doubleDown

1
@doubleDown Это не должно быть универсальным решением (где есть много возможных кандидатов), но в большинстве случаев вы действительно считаете, что нажатие n5 или 6 раз более обременительно, чем добавление \(\%5l\|\%12l\)к оператору замены?
Дин

Я считаю это полезным, я хотел изменить каждую вторую строку, это было бы быстрее, чем то, что я в итоге сделал.
tiktak 02

9

Интересный вопрос. Похоже, есть только выбор диапазона и нет множественного выбора:

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

Однако, если у вас есть что-то особенное в строках 5 и 12, вы можете использовать :gоператор. Если ваш файл выглядит так (цифры только для справки):

 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

И вы хотите заменить oneна enoна линиях , где есть enilвместо того , чтобы line:

:g/enil/s/one/eno/

5
на самом деле это предполагает многое
doubleDown

1

Вы можете использовать ed- строчно-ориентированный текстовый редактор с командами, аналогичными vi и vim. Вероятно, он появился раньше vi и vim.

В сценарии (используя здесь документ, который обрабатывает ввод до маркера EndCommand) это будет выглядеть так:

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

Очевидно, что команды ed можно также использовать в командной строке.


3
Я не вижу преимущества перед vimальтернативой.
Bernhard

1
То же самое можно сделать и с Vim; числа могут быть помещены перед :s, но все же остается дублирование :sкоманды (чего избегает решение romainl).
Ingo Karkat

На мой взгляд, пользователь может захотеть выбрать для редактирования гораздо больше, чем две строки. В этом случае мог быть интересен неинтерактивный подход, который, AFAIK, не может быть реализован с помощью vim.
Suspectus

1
О, Vim может это сделать (например, в режиме «Ex»), но вы правы, что другой инструмент должен быть предпочтительнее интерактивного редактора. sedХотя я бы предпочел ...
Инго Каркат
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.