Эффективный способ рефакторинга класса / метода / строки в каталоге с использованием vim - PullRequest
12 голосов
/ 26 августа 2011

До сих пор я вручную рефакторинг кода с помощью операции поиска и замены

%s:/stringiwanttoreplace/newstring/g 

в vim.

Но это медленный и трудоемкий процесс, если у меня есть stringiwanttoreplace во многих файлах внутри определенного каталога.

Мой текущий / типичный медленный и трудоемкий процесс включает в себя grep: -

grep -rn "stringiwanttoreplace" .

в моем терминале, чтобы показать все местоположения / имена файлов, где stringiwanttoreplace ; и теперь, когда я знаю, какие файлы содержат stringiwanttoreplace , я открою каждый файл один за другим, чтобы выполнить операцию поиска и замены в каждом файле.

Есть ли более эффективный рабочий процесс (в vim) для этого?

РАЗЪЯСНЕНИЕ: Я бы предпочел решение на основе vim вместо bash-скрипта / однострочного.

Ответы [ 6 ]

15 голосов
/ 26 августа 2011

Вот полная последовательность команд, которую я бы использовал:

/stringiwanttoreplace
:vimgrep /<c-r>// **
:Qargs
:argdo %s//newstring/g
:argdo update

В первой строке мы ищем целевой шаблон.Это заполняет последний регистр шаблона поиска (:help quote/), что означает, что нам не придется вводить его снова полностью.

Команда :vimgrep ищет весь проектдля указанного шаблона.Введите <c-r>/ как ctlr + r , а затем / - это вставляет содержимое последнего регистра шаблона поиска в командную строку.Первый и последний символы / являются разделителями для поля поиска.Трейлинг ** говорит Vim заглянуть внутрь каждого файла и каталога под текущим каталогом.

На этом этапе список быстрых исправлений будет заполнен поисковыми совпадениями из всех соответствующих файлов.:Qargs - это пользовательская команда, которая заполняет список аргументов всеми файлами, перечисленными в списке быстрых исправлений.Вот реализация:

command! -nargs=0 -bar Qargs execute 'args ' . QuickfixFilenames()
function! QuickfixFilenames()
  " Building a hash ensures we get each buffer only once
  let buffer_numbers = {}
  for quickfix_item in getqflist()
    let buffer_numbers[quickfix_item['bufnr']] = bufname(quickfix_item['bufnr'])
  endfor
  return join(values(buffer_numbers))
endfunction

Добавьте это к вашему vimrc файлу.

После запуска :Qargs наш список аргументов должен теперь содержать все файлы, которые включают нашу целевую строку.Таким образом, мы можем запустить команду подстановки с :argdo, чтобы выполнить команду в каждом файле.Мы можем оставить поле поиска команды замещения пустым, и оно будет автоматически использовать самый последний шаблон поиска.Если вы хотите, вы можете включить флаг c при запуске команды замещения, тогда вам будет предложено подтвердить.

Наконец, команда :argdo update сохраняет каждый файл, который был изменен.

Как указал @ Peter Rincker , вы должны убедиться, что опция Vim's 'hidden' включена, иначе она вызовет ошибку при попытке переключиться на другой буфер перед тем, какзапись любых изменений в активный буфер.

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

:Qargs | argdo %s//replacement/gc | update

Команда :Qargs взята из этого ответа (мной), который, в свою очередь, был вдохновлен этим ответом DrAl .Очень подобное решение было опубликовано @ ib , что подсказывает мне, что Vim должен действительно реализовать что-то вроде :quickfixdo изначально.

4 голосов
/ 26 августа 2011

Если вы действительно хотите сделать это в Vim, вы можете следовать советам здесь .

3 голосов
/ 26 августа 2011

Вы можете вызвать это из Vim (:!find ...), но вам не нужно:

find . -type f | xargs sed -i 's/stringiwanttoreplace/newstring/g'

Точно настроить выбор файла с помощью десятков описанных параметровв

man find

(например, заменить только в файлах HTML: -name \*.html)

Это решение попытается выполнить попытку замены во всех файлах.Вы можете фильтровать это через grep раньше, но это просто делает вдвое больше работы без выгоды.

Кстати: sed использует почти такой же синтаксис для регулярных выражений, как Vimвытекает из той же истории).

2 голосов
/ 26 августа 2011

Вы можете открыть все файлы и набрать

:bufdo :s/stringiwanttoreplace/newstring/g

Он выполняет поиск / замену во всех ваших буферах.

1 голос
/ 26 августа 2011

vim7 имеет встроенную рекурсивную команду grep

:vimgrep /pattern/[j][g] file file1 file2 ... fileN

результат будет отображен в окне быстрого исправления (: help quickfix)

для рекурсивного поиска используйте **-wildcard, например

**/*.c, для поиска в текущей папке и рекурсивно во всех подкаталогах.

1 голос
/ 26 августа 2011

Вам не нужно vim, чтобы сделать это, вы можете использовать инструменты командной строки. Использование sed в цикле в списке файлов, чтобы сделать это автоматически. Примерно так:

for each in `grep -l "stringiwanttoreplace" *` ;
do
    cat $each | sed -e "s/stringiwanttoreplace/newstring/g" > $each
; done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...