Найти и заменить строки в vim на несколько строк

354

Я могу сделать :%s/<search_string>/<replace_string>/gдля замены строки в файле, или :s/<search_string>/<replace_string>/заменить в текущей строке.

Как выбрать и заменить слова из отдельных строк в vim?

Пример: заменить текст из строк 6-10, 14-18но не из 11-13.

му 無
источник

Ответы:

255

Команда :&&повторяет последнюю замену с теми же флагами. Вы можете предоставить ему дополнительные диапазоны (и объединить столько, сколько хотите):

:6,10s/<search_string>/<replace_string>/g | 14,18&&

Если у вас много диапазонов , я бы предпочел использовать цикл:

:for range in split('6,10 14,18')| exe range 's/<search_string>/<replace_string>/g' | endfor
Инго Каркат
источник
5
Спасибо. Примечание для будущих пользователей - :6,10s/<search_string>/<replace_string>/g | :14,18&& | :20,23&& | :28,31&&также будет работать, forцикл сделает его более простым для запоминания и выполнения.
mu 無
5
Рад, что вам это нравится! :На последующих команд не является обязательным, кстати, так что вы можете сэкономить еще несколько нажатий клавиш.
Инго Каркат
2
:&&спасет меня сотни нажатий клавиш в неделю. Спасибо!
pdoherty926
Он работает без «g» в конце в моем vim. Так что, возможно, когда вы указываете диапазон строк, ему не нужен глобальный флаг
Tayyar R
3
@TayyarR Диапазон охватывает линии (так сказать, по вертикали), в то время как флаг 'g' определяет, будут ли заменены только одно или все совпадения в строке (по горизонтали).
Инго Каркат
387

Заменить все:

:%s/foo/bar/g

Найдите каждое вхождение 'foo' (во всех строках) и замените его на 'bar'.

Для конкретных строк:

:6,10s/foo/bar/g

Измените каждое «foo» на «bar» для всех строк от строки 6 до строки 10 включительно.

Джаянт Рамачандран
источник
4
Какова цель / г здесь? Извините, я новичок в Linux
Раджа Анбажаган
4
@RajaAnbazhagan В последней части этого выражения после последнего /указываются флаги для операции. Эта команда обычно заменяет первое совпадение в строке; С gфлагом это заменит все вхождения.
Малый
17
Вы должны действительно ссылаться на свои источники (например, vim.wikia.com/wiki/Search_and_replace), если вы собираетесь копировать и передавать работы другого человека.
Андрей С.
2
%Вещь делает работу! В противном случае, это только первый случай.
Сантош Кумар
8
%=> запустить эту команду на всех строках. g=> сопоставить несколько вхождений в одной строке.
Shaahiin
55

В качестве примечания, вместо того, чтобы вводить номера строк, просто выделите строки, которые вы хотите найти / заменить в одном из визуальных режимов:

  • VISUALрежим ( V)
  • VISUAL BLOCKрежим ( Ctrl+ V)
  • VISUAL LINEрежим ( Shift+ V, лучше всего работает в вашем случае)

После того как вы выбрали строки для замены, введите команду:

:s/<search_string>/<replace_string>/g

Вы заметите, что диапазон '<,'>будет вставлен автоматически для вас:

:'<,'>s/<search_string>/<replace_string>/g

Здесь '<просто означает первую выделенную строку и '>означает последнюю выделенную строку .

Обратите внимание , что поведение может быть неожиданным , когда в NORMALрежиме: '<и '>указывают на начало и конец последнего изюминкой сделано в одном из VISUALрежимов. Вместо этого в NORMALрежиме .можно использовать специальный номер строки , который просто означает текущую строку . Следовательно, вы можете найти / заменить только текущую строку следующим образом:

:.s/<search_string>/<replace_string>/g

Следует также отметить, что вставка секунды :между диапазоном и командой find / replace не причиняет вреда, другими словами, эти команды будут работать:

:'<,'>:s/<search_string>/<replace_string>/g
:.:s/<search_string>/<replace_string>/g
Аттила О.
источник
1
> Пример: заменить текст из строк 6-10, 14-18, но не из 11-13. - разве ваш ответ не отвечает на этот вопрос?
Пой
27

Вы можете сделать это с двумя последовательностями поиска / замены

  :6,10s/<search_string>/<replace_string>/g
  :14,18s/<search_string>/<replace_string>/g

Во второй раз все, что вам нужно настроить, это диапазон, поэтому вместо того, чтобы вводить все, я вспомнил бы последнюю команду и отредактировал только диапазон

Ливен Керсмакерс
источник
21

В vim, если вы не уверены, какие строки будут затронуты, используйте ниже

 :%s/foo/bar/gc  

Измените каждое «foo» на «bar», но сначала запросите подтверждение. Нажмите «y» для «да» и «n» для «нет». Не забудьте сохранить после этого

:wq
SMJ
источник
2
Вы можете использовать cфлаг в дополнение к указанию диапазона, так что :6,10s/<search_string>/<replace_string>/cработает. cобозначает confirm. Я использую cфлаг довольно часто, чтобы предотвратить случайную замену слов, где я не думал о том, что они там тоже существуют.
Вольфсон
16

VI поиск и замена примеров команд

Допустим, вы хотели бы найти слово под названием «foo» и заменить его на «bar».

Первый удар по [Esc]клавише

Введите: (двоеточие) %s/foo/bar/и нажмите клавишу [Ввод]

:%s/foo/bar/

arnav
источник
11
Ваша :%s/<search_string>/<replace_string>/gкоманда заменит все вхождения во всем файле. Не совсем ответ на вопрос, но, тем не менее, полезный :)
tanius
@tanius На самом деле это был самый прямой ответ на мою проблему. Вы можете изменить вопрос на «Найти и заменить строки в vim на« выбранных »строках»
Омид N
9

Нам не нужно вводить текущий номер строки.

Если вы хотели бы изменить каждый fooв barтечение текущей строки ( .) и два следующих строк ( +2), просто сделать:

:.,+2s/foo/bar/g

Если вы хотите подтвердить до внесения изменений, замените gна gc:

:.,+2s/foo/bar/gc
lingjiankong
источник
Еще одна приятная вещь, которую я часто использую, - :.,$s/foo/bar/gcэто поиск и замена, начиная с текущей строки и до конца файла.
Вольфсон
3

Поиск и замена

:%s/search\|search2\|search3/replace/gci

g => глобальный поиск

c => Сначала запросите подтверждение

я => без учета регистра

Если вы хотите прямую замену без подтверждения, используйте команду ниже

:%s/search/replace/g

Если вы хотите подтверждение для каждой замены, выполните команду ниже

:%s/search/replace/gc

Сначала запросите подтверждение, здесь поиск будет без учета регистра.

:%s/search/replace/gci
Рахул Рави
источник
1

Задать диапазон с помощью визуального выбора можно, но когда есть очень простые операции с парой строк, которые могут быть выбраны оператором, лучше всего применять эти команды в качестве операторов.

К сожалению, этого нельзя сделать с помощью стандартных команд vim. Вы можете сделать своего рода обходной путь, используя! (фильтр) оператор и любой текстовый объект. Например, чтобы применить операцию к абзацу, вы можете сделать:

!ip

Это должно читаться как «Применить оператор! Внутри абзаца». Оператор фильтра запускает командный режим и автоматически вставляет диапазон строк, за которым следует буква "!" что вы можете удалить сразу после. Если вы примените это, к следующему абзацу:

1
2  Repellendus qui velit vel ullam!
3  ipsam sint modi! velit ipsam sint
4  modi! Debitis dolorum distinctio
5  mollitia vel ullam! Repellendus qui
6  Debitis dolorum distinctio mollitia
7  vel ullam! ipsam
8
9  More text around here

Результат после нажатия "! Ap" будет выглядеть так:

:.,.+5

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

Плохая часть в том, что это не проще, чем выбирать текст для последующего применения оператора. Хорошая часть заключается в том, что это может повторить вставку диапазона для других похожих текстовых диапазонов (в данном случае, абзацев) с заметно отличающимся размером. Т.е., если позже вы захотите выбрать диапазон большего абзаца, то '.' будет ли это правильно.

Также, если вам нравится идея использования семантических текстовых объектов для выбора диапазона операций, вы можете проверить мой плагин EXtend.vim, который может делать то же самое, но более простым способом.

Сол Аксель Мартинес Ортиз
источник
0

Чтобы ответить на этот вопрос:

:40,50s/foo/bar/g

замените foo на bar в этих строках между 40-й строкой и 50-й строкой (включительно), при выполнении этой команды вы можете в данный момент в любой строке.

:50,40s/foo/bar/g

также работает, vim запросит у вас подтверждение и затем заменит вас, как если бы вы ввели первую команду.

:,50s/foo/bar/g

замените foo на bar в этих строках между строкой, в которой вы находитесь, и 50-й строкой (включительно). (если вы находитесь в очереди ПОСЛЕ 50-й строки, vim снова запросит подтверждение)

Чтобы прояснить разницу между vim и плагином vrapper в Eclipse:

Обратите внимание, что в varpper

:,50s/foo/bar/g Команда НЕ будет работать.

:50,40s/foo/bar/g будет работать без запроса подтверждения.

(Для Vrapper версии 0.74.0 или старше).

ZhaoGang
источник
-5
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal

Предположим, если вы хотите заменить вышеупомянутое другой информацией.

COMMAND(:%s/\/sys\/sim\/source\/gm\/kg\/jl\/ls\/owow\/lsal/sys.pkg.mpu.umc.kdk./g)

В этом случае вышеприведенное будет заменено на ( sys.pkg.mpu.umc.kdk.).

Сай Ганеш
источник
Я не уверен, что это действительно отвечает на вопрос. Из вопроса выясняется, что спрашивающий уже знает, как использовать %sдля изменения ввода, но хочет знать, как сделать это «полуглобально» (т.е. его спецификация - строки 6-10 и 14-18, но не в строках 11- 13).
Брэндон Бак
1
И что такое "КОМАНДА"? И вы страдаете от синдрома склонности зубочистки .
Мартин Турной
Для того, чтобы вылечить этот синдром, вы можете использовать другой символ в качестве разделителя вместо значения по умолчанию /, например !, @, _::%s_/sys/sim/source/gm/kg/jl/ls/owow/lsal_sys.pkg.mpu.umc.kdk_g
MortezaE