Я узнал о команде замены Vim...
:%s/replaceme/replacement/gi
И vimgrep...
:vimgrep /findme/gj project/**/*.rb
Есть ли способ объединить их, чтобы выполнить замену во всех файлах в каталоге?
Я узнал о команде замены Vim...
:%s/replaceme/replacement/gi
И vimgrep...
:vimgrep /findme/gj project/**/*.rb
Есть ли способ объединить их, чтобы выполнить замену во всех файлах в каталоге?
Несмотря на то, что я пользователь Vim, я обычно использую find и sed для такого рода вещей. Синтаксис регулярного выражения для sed аналогичен Vim (они оба являются потомками ed), хотя и не идентичны. С помощью GNU sed вы также можете использовать -i для редактирования на месте (обычно sed испускает измененную версию в стандартный вывод).
Например:
find proj -name '*.rb' -type f -exec sed -i -e 's/regex/replacement/g' -- {} +
По частям:
proj= поиск в дереве "proj" -name '*.rb'= для вещей, имена которых соответствуют '*.rb'-type f= и являются обычными файлами (не каталоги, каналы, символические ссылки и т.д.).-exec sed= запустить sed с этими аргументами:
-i= с изменениями на месте-e 's/regex/replacement/g'= выполнить команду "substitute" (которая почти идентична Vim :s, но обратите внимание на отсутствие % - это значение по умолчанию в sed)--= конец флагов, имена файлов начинаются здесь{}= this сообщает find, что найденные имена файлов должны быть помещены в командную строку sed здесь+= this сообщает find, что действие -exec закончено, и мы хотим сгруппировать аргументы как можно меньше sed вызовов (как правило, более эффективно, чем запуск одного раза на имя файла). Чтобы запустить его один раз для имени файла, вы можете использовать \; вместо +.Это общее решение с GNU sed и find. Это может быть сокращено в особых случаях. Например, если вы знаете, что ваш шаблон имени не будет соответствовать каталогам, вы можете оставить -type f. Если вы знаете, что ни один из ваших файлов не начинается с -, вы можете оставить --. Вот ответ, который я отправил на другой вопрос с более подробной информацией об отправке имен файлов, найденных с помощью find, в другие команды.
args и argdo должны делать то, что вам нужно, например
:args spec/javascripts/**/*.*
:argdo %s/foo/bar/g
Смотрите эту страницу.
Вы можете запустить vimgrep, затем записать макрос, который поступает в каждую строку в выводе vimgrep, и выполняет замену, что-то вроде этого: (не вводите # комментариев!)
:set autowrite #automatically save the file when we change buffers
:vimgrep /pattern/ ./**/files
qa #start recording macro in register a
:s/pattern/replace/g #replace on the current line
:cnext #go to next matching line
q #stop recording
[email protected] #repeat the macro 10000 times, or until stopped by
#an "error" such as reaching the end of the list
:set noautowrite
Я не тестировал его, поэтому может потребоваться небольшая настройка - протестируйте его на некоторых файлах, которые вы не пропустите сначала.
Преимущество этого над sed заключается в том, что регулярное выражение Vim более мощное, и вы можете добавить опцию c: s для проверки каждой замены.
Edit: Я изменил свой оригинальный пост, так как это было неправильно. Я использовал: 1vimgrep, чтобы найти первое совпадение в каждом файле, но я неправильно читаю документы - он находит только одно совпадение во всех файлах.
Там есть плагин, который пытается сделать именно это: Vimgrep Replace.
О, подождите... есть другие: Global Replace, EasyGrep.
Для решения без плагинов, возможно, argdo поможет, если вы можете получить вывод vimgrep в список аргументов (который может быть установлен с помощью args), но я не могу понять детали. Я был бы рад, если бы кто-то принял эту идею и улучшил ее... так вот, это так.
Основная идея первого плагина (я бы предположила, что другие тоже...) заключается в использовании vimgrep, а затем цикл через совпадения с :cnext и применить команду подстановки в каждой строке. Функция для выполнения этого может быть достаточно маленькой, чтобы поместить ее в .vimrc. (Может быть, вы можете поднять его из источников плагинов?)
(Я полагаю, что hgimenez может быть включен в решение, но независимо от того, будет ли оно соответствовать, вероятно, будет зависеть от количества обрабатываемых файлов... Плагины должны быть в порядке независимо.)
Одним из способов было бы открыть все файлы, которые вы хотите запустить подстановкой (или любую команду), и запустить :bufdo <cmd>, который будет запускать <cmd> во всех открытых буферах.
Это работает для небольшого количества файлов.
vim `find. -type f `
: bufdo% s/pattern/replacement/gec | обновление