Как выполнить поиск и заменить с помощью 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, если подтверждение не требуется.