Как выполнить поиск и заменить с помощью ack в vim?
Я использую плагин Ack в Vim, который помогает мне быстро искать строки в моем проекте. Однако иногда я хочу заменить все или некоторые вхождения найденных строк. Вы можете выполнить какой-то глобальный поиск и заменить его с помощью Vim arglist (source)
:args app/views/*/*
:argdo %s/, :expire.*)/)/ge | update
Но вместо использования args
, я бы предпочел выполнить поиск через Ack, а затем выполнить замену во всех найденных файлах. Есть ли способ сделать это аналогично команде argdo
?
Ответы
Ответ 1
Я решил использовать ack и Perl для решения этой проблемы вне Vim, поэтому я могу использовать более мощные регулярные выражения Perl вместо подмножества GNU. Вы можете сопоставить это с ключевым штрихом в своем vimrc.
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/.
Ответ 2
Я не считаю, что есть встроенный способ сделать это, но это должно быть легко сделать.
Что вам нужно сделать, так это создать команду, которая вызывает пользовательскую функцию. Затем функция должна использовать функцию getqflist()
, чтобы получить все записи в списке quickfix и exe
, чтобы выполнить грязную работу. Будьте осторожны, что вы передаете в качестве аргумента!
" Define a command to make it easier to use
command! -nargs=+ QFDo call QFDo(<q-args>)
" Function that does the work
function! QFDo(command)
" Create a dictionary so that we can
" get the list of buffers rather than the
" list of lines in buffers (easy way
" to get unique entries)
let buffer_numbers = {}
" For each entry, use the buffer number as
" a dictionary key (won't get repeats)
for fixlist_entry in getqflist()
let buffer_numbers[fixlist_entry['bufnr']] = 1
endfor
" Make it into a list as it seems cleaner
let buffer_number_list = keys(buffer_numbers)
" For each buffer
for num in buffer_number_list
" Select the buffer
exe 'buffer' num
" Run the command that passed as an argument
exe a:command
" Save if necessary
update
endfor
endfunction
Ответ 3
Теперь у Vim есть новая команда cdo
, которая будет запускать заданную команду в каждой строке списка quickfix.
Итак, вы можете использовать
:Ack pattern
:cdo s/pattern/newpattern/g
Ответ 4
Вы можете использовать ack таким образом
:args `ack -l User app/`
:argdo %s/, :expire.*)/)/ge | update
Или используйте ag
:args `ag -l User app/`
:argdo %s/, :expire.*)/)/gec | w
Ответ 5
Я использую MacVim (активируется с mvim
в оболочке). Я передаю результаты ack
в mvim
:
mvim -f $(ack -l [email protected])
Затем в MacVim я выполняю поиск/замену с помощью bufdo
:
:bufdo %s/SEARCH/REPLACE/gce | update
Опустите параметр c
, если подтверждение не требуется.