Шукайте та замінюйте vim у конкретних рядках


94

Я можу використовувати

:5,12s/foo/bar/g

шукати fooта замінювати його barміж рядками 5 і 12. Як я можу це зробити лише в рядках 5 і 12 (а не в рядках між ними)?

Відповіді:


75

Vim має спеціальні атоми регулярних виразів, які збігаються в певних рядках, стовпцях тощо; Ви можете використовувати їх (можливо, на додаток до діапазону), щоб обмежити збіги:

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

Подивитися :help /\%l


8
Більш складний спосіб, ніж я очікував, але ідеально відповідає на моє запитання. Дякую!
pfnuesel

55

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

:5s/foo/bar
:12&

Як зазначив Інго, :&забуває ваші прапори. Оскільки ви використовуєте /g, правильною командою буде :&&:

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

Побачити :help :&і друзів.


10
+1 за використання незрозумілого :&. Якщо є прапори ( s/../../g), все-таки потрібно використовувати :&&...
Інго Каркат,

10
@IngoKarkat, чесно кажучи, я вважаю \(\%5l\|\%12l\)більш неясним, ніж:&
doubleDown

13

Ви завжди можете додати a cдо кінця. Це вимагатиме підтвердження для кожного матчу.

:5,12s/foo/bar/gc

1
Це може бути кошмаром, якщо між 5 і 12 рядками буде багато матчів (майте на увазі, що gу грі є прапор)
doubleDown

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

Я вважаю це корисним, я хотів змінити будь-який інший рядок, це було б швидше, ніж те, що я в підсумку зробив.
тиктак 02.03.17

8

Цікаве питання. Здається, що існує лише вибір діапазону, а не вибір кількох рядків:

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альтернативою.
Бернхард

1
І те саме можна зробити і з Vim; цифри насправді можна поставити перед :s, але все ще існує дублювання :sкоманди (чого рішення romainl уникає).
Інго Каркат

На мою думку, користувач міг захотіти вибрати для редагування значно більше двох рядків. У такому випадку міг би представляти інтерес неінтерактивний підхід - чого AFAIK неможливо зробити за допомогою vim.
suspectus

1
О, Vim може це зробити (наприклад, у режимі "Ex"), але ви маєте рацію, що іншому інструменту слід віддавати перевагу над інтерактивним редактором. sedОднак моїм уподобанням було б ...
Інго Каркат,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.