Поиск и замена в Vim по всем файлам проекта - PullRequest
107 голосов
/ 26 января 2011

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

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

:args ./**

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

:argdo %s/Search/Replace/gce

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

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

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

Ответы [ 9 ]

93 голосов
/ 28 января 2011

Другой большой вариант здесь просто не использовать 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/'

и так далее!

51 голосов
/ 24 июня 2016

Благодаря недавно добавленной команде 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-й команды, если вы хотите заменить каждый поисковый запрос без подтверждения каждый раз)

33 голосов
/ 05 января 2012

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

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

Объяснение

извед

ack - это потрясающий инструмент командной строки, представляющий собой смесь grep, find и полных регулярных выражений Perl (не только подмножество 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/.

26 голосов
/ 26 января 2011

Greplace хорошо работает для меня.

На github также есть готовая к патогенам версия .

22 голосов
/ 26 января 2011

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

:noautocmd vim /Search/ **/*
:set hidden
:cfirst
qa
:%s//Replace/gce
:cnf
q
1000@a
:wa

Пояснение:

  • :noautocmd vim /Search/ **/* & # x21D2; поиск (vim - это аббревиатура для vimgrep) шаблона во всех файлах во всех подкаталогах cwd без запуска autocmds (:noautocmd), ради скорости.
  • :set hidden & # x21d2; разрешить изменение буферов, не отображаемых в окне (может быть в вашем vimrc)
  • :cfirst & # x21d2; перейти к первому результату поиска
  • qa & # x21d2; начать запись макроса в регистр a
  • :%s//Replace/gce & # x21d2; замените все вхождения последнего шаблона поиска (все еще /Search/ в то время) на Replace:
    • несколько раз на одной строке (g флаг)
    • с подтверждением пользователя (c флаг)
    • без ошибок, если шаблон не найден (e флаг)
  • :cnf & # x21d2; перейти к следующему файлу в списке, созданном командой vim
  • q & # x21d2; остановить запись макроса
  • 1000@a & # x21d2; воспроизвести макрос, записанный в регистр 1000 раз
  • :wa & # x21d2; сохранить все измененные буферы

* РЕДАКТИРОВАТЬ * Vim 8 way:

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

:noautocmd vim /Search/ **/*
:set hidden
:cfdo %s//Replace/gce
:wa
21 голосов
/ 23 января 2013

Заполните :args из команды оболочки

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

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

:args `ack -l pattern`

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

Или с простым старым добром, думаю, это будет:

:args `grep -lr pattern .`  


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

:argdo %s/pattern/replacement/gce


Заполнить :args из списка быстрых исправлений

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

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

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

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

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

Ссылки

  1. : h {arglist} - vimdoc.sourceforge.net/htmldoc/editing.html# averagearglist отпуска
  2. ack - betterthangrep.com /
  3. ack.vim - github.com / mileszs / ack.vim
  4. беглец - github.com / tpope / vim-fugitive
7 голосов
/ 07 ноября 2016

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

far.vom

5 голосов
/ 30 июня 2015

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

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

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

ctrlsf_edit_demo

0 голосов
/ 13 декабря 2014

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

На основании ответа @ 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...