Поиск и замена в Vim по всем файлам проекта

Я ищу лучший способ выполнить поиск и замену (с подтверждением) во всех файлах проекта в Vim. Под "файлами проекта" я имею в виду файлы в текущем каталоге, некоторые из которых не должны быть открытыми.

Одним из способов сделать это может быть просто открытие всех файлов в текущем каталоге:

:args ./**

а затем выполните поиск и замену во всех открытых файлах:

:argdo %s/Search/Replace/gce

Однако, когда я это делаю, использование памяти Vim перескакивает с пары десятков МБ на более чем 2 ГБ, что не работает для меня.

У меня также установлен плагин EasyGrep, но он почти никогда не работает/либо он не находит всех вхождений, либо просто зависает, пока не нажимаю Ctrl C. До сих пор мой предпочтительный способ выполнить эту задачу для ack-grep для поискового запроса, используя его окно быстрого открытия, открыть любой файл, содержащий этот термин и ранее не открывшийся, и, наконец, :bufdo %s/Search/Replace/gce.

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

Ответ 2

Другой большой вариант здесь просто не использовать vim:

sed -i 's/pattern/replacement/' <files>

или если у вас есть способ генерации списка файлов, возможно, что-то вроде этого:

find . -name *.cpp | xargs sed -i 's/pattern/replacement/'
grep -rl 'pattern1' | xargs sed -i 's/pattern2/replacement/'

и т.д.

Ответ 3

Я решил использовать ack и Perl для решения этой проблемы, чтобы воспользоваться более мощными полными регулярными выражениями Perl, а не подмножеством GNU.

ack -l 'pattern' | xargs perl -pi -E 's/pattern/replacement/g'

Объяснение

извед

ack - это отличный инструмент командной строки, который представляет собой сочетание grep, find и полных регулярных выражений (а не только подмножества GNU). Его написанный на чистом Perl, его быстрый, он имеет подсветку синтаксиса, работает на Windows и более дружелюбен к программистам, чем традиционные инструменты командной строки. Установите его на Ubuntu с помощью sudo apt-get install ack-grep.

xargs

Xargs - это старый инструмент командной строки unix. Он считывает элементы со стандартного ввода и выполняет указанную команду, за которой следуют элементы, считанные для стандартного ввода. Таким образом, в основном список файлов, созданных ack, добавляется в конец команды perl -pi -E 's/pattern/replacemnt/g'.

perl -pi

Perl - это язык программирования. Параметр -p заставляет Perl создавать цикл вокруг вашей программы, который выполняет итерацию по аргументам имени файла. Опция -i заставляет Perl редактировать файл на месте. Вы можете изменить это для создания резервных копий. Параметр -E заставляет Perl выполнять одну строку кода, указанную в качестве программы. В нашем случае программа является просто заменой регулярного выражения Perl. Дополнительные сведения о параметрах командной строки Perl perldoc perlrun. Для получения дополнительной информации о Perl см. http://www.perl.org/.

Ответ 4

может сделать это:

:noautocmd vim /Search/ **/*
:set hidden
:cfirst
qa
:%s//Replace/gce
:cnf
q
[email protected]
:wa

Пояснение:

  • :noautocmd vim /Search/ **/* ⇒ lookup (vim is an abbreviation for vimgrep) pattern in all files in all subdirectories of the cwd without triggering autocmds (:noautocmd), for speed sake.
  • :set hidden ⇒ allow having modified buffers not displayed in a window (could be in your vimrc)
  • :cfirst ⇒ jump to first search result
  • qa ⇒ start recording a macro into register a
  • :%s//Replace/gce ⇒ replace all occurrences of the last search pattern (still /Search/ at that time) with Replace:
    • несколько раз на одной строке (флаг g)
    • с подтверждением пользователя (флаг c)
    • без ошибок, если шаблон не найден (e)
  • :cnf ⇒ jump to next file in the list created by the vim command
  • q ⇒ stop recording macro
  • [email protected] ⇒ play macro stored in register a 1000 times
  • :wa ⇒ save all modified buffers

* EDIT * Vim 8 way:

Начиная с Vim 8 есть лучший способ сделать это, так как :cfdo выполняет итерацию по всем файлам в списке quickfix:

:noautocmd vim /Search/ **/*
:set hidden
:cfdo %s//Replace/gce
:wa

Ответ 5

Залить :args из командной строки

Возможно (в некоторых операционных системах 1)) для отправки файлов :args с помощью команды оболочки.

Например, если у вас установлен ack 2,

:args `ack -l pattern`

попросит ack вернуть список файлов, содержащих 'pattern', и поместить их в список аргументов.

Или с простым ol 'grep, я предполагаю, что это будет:

:args `grep -lr pattern .`  


Затем вы можете просто использовать :argdo, как описано в OP:

:argdo %s/pattern/replacement/gce


Залить :args из списка быстрого удаления

Также проверьте ответ nelstrom на связанный с ним вопрос, описывающий простую пользовательскую команду, которая заполняет список arglist из текущего списка быстрого исправления. Это отлично работает со многими командами и плагинами, выход которых попадает в список быстрого списка (:vimgrep, :Ack 3:Ggrep 4).

Последовательность выполнения широкомасштабного поиска проекта может быть выполнена с помощью:

:vimgrep /pattern/ **/*
:Qargs 
:argdo %s/findme/replacement/gc

где :Qargs - это вызов пользовательской команды, которая заполняет список arglist из списка quickfix.

Вы также найдете ссылки в последующем обсуждении на простые плагины, которые получают этот рабочий процесс до двух или трех команд.

Ссылки

Ответ 6

Благодаря недавно добавленной команде cdo, вы можете сделать это двумя простыми командами, используя любой инструмент grep, который вы установили, Никаких дополнительных плагинов не требуется!:

1. :grep <search term>
2. :cdo %s/<search term>/<replace term>/gc
3. (If you want to save the changes in all files) :cdo update

(cdo выполняет данную команду для каждого термина в списке быстрого исправления, который заполняется вашей командой grep.)

(Удалите c в конце 2-й команды, если вы хотите заменить каждый термин поиска, не подтверждая каждый раз)

Ответ 7

Еще один вариант в 2016 году, far.vim плагин:

far.vom

Ответ 8

Если вы не возражаете против введения внешней зависимости, я заварил плагин ctrlsf.vim (зависит от ack или ag) для выполнения задания.

Он может форматировать и отображать результат поиска из ack/ag и синхронизировать ваши изменения в буфере результатов с фактическими файлами на диске.

Возможно, следующая демонстрация объясняет больше

ctrlsf_edit_demo

Ответ 9

В принципе, мне нужна замена в одной команде и, что более важно, внутри самого vim

Основываясь на ответе by @Jefromi, я создал ярлык для клавиатуры, который я установил в моем .vimrc файле, подобном этому

nmap <leader>r :!grep -r -l  * \| xargs sed -i -e 's///g'

теперь из vim, на ударе лидера + r Я получаю команду, загруженную в vim, которую я редактирую, как показано ниже,

:!grep -r -l <find> <file pattern> | xargs sed -i -e 's/<find>/<replace>/g'

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