Пошук Vim замінить усі файли в поточній папці (проект)


37

Одне з відкритих запитань щодо Vim - це чи є спосіб здійснити пошук / заміну в поточному проекті (майте на собі, якщо я буду використовувати це поняття, успадковане від інших редакторів).

Наприклад, припустимо, що я хочу шукати у своїх проектах файли назви методу та перейменувати всі екземпляри виклику цього методу.

Ось так я можу продовжити Sublime.

введіть тут опис зображення

Як би ви це зробили у Vim (можливо, MacVim), не покладаючись на інші програми, такі як ackабо sed?

Відповіді:


35

Існує кілька способів зробити це.

Всередині поточного каталогу

Якщо ви хочете виконати пошук / заміну в дереві проекту, ви можете скористатися списком аргументів Vim .

Просто відкрийте Vim та використовуйте :argsкоманду для заповнення списку аргументів. Ви можете передавати кілька файлів і навіть глобуси.

Наприклад, :args **/*.rbрекурсивно шукатимуть у поточному каталозі рубінові файли. Зауважте, що це також як відкриття Vim з vim **/*.rb. Ви навіть можете скористатися командою shell, findщоб отримати список усіх файлів у поточному каталозі, запустивши:

:args `find . -type f`

Ви можете переглянути поточний список аргументів, запустивши :argsйого сам. Якщо ви хочете додати або видалити файли зі списку, ви можете використовувати відповідно команди :argaddабо :argdelete.

Коли ви задоволені списком, тепер ви можете використовувати потужну :argdoкоманду Vim, яка виконує команду для кожного файлу зі списку аргументів::argdo %s/search/replace/g

Ось кілька порад щодо пошуку (на основі деяких коментарів):

  1. Використовуйте межу слова, якщо ви хочете шукати "foo", але не "foo_bar". Використовуйте \<та \>конструюйте навколо структури пошуку так::argdo %s/\<search\>/foobar/g
  2. Використовуйте /cпрапор пошуку, якщо ви хочете, щоб Vim запитав підтвердження перед заміною пошукового терміну.
  3. Використовуйте /eпрапор пошуку, якщо ви хочете пропустити помилки "шаблон не знайдено".
  4. Ви також можете зберегти файл після виконання пошуку: :argdo %s/search/replace/g | update. Тут :updateвикористовується, оскільки збереже файл лише у тому випадку, якщо він змінився.

Відкрити буфери

Якщо у вас вже відкриті буфери, ви хочете виконати пошук / заміну, ви можете використовувати :bufdoкоманду, яка виконує команду для кожного файлу у вашому списку буферів ( :ls).

Команда дуже схожа на :argdo: :bufdo %s/search/replace/g

Подібне до :argdoта :bufdo, є :windoі :tabdoте, що діє на вікна та вкладки відповідно. Вони рідше використовуються, але все ж корисно знати.


4
Можливо, може бути хорошою ідеєю використовувати /cпрапор для підтвердження заміни.
romainl

3
Я також рекомендую використовувати межі слів \<і \>навколо, searchщоб уникнути часткової заміни слова.
tommcdo

1
Ще один коментар - це те, що робочий каталог vim за замовчуванням знаходиться там, де ви запустили vim, а не в каталозі поточного файлу. Ви можете встановити робочий каталог на поточний файл за допомогою :cd %:p:h. Інші параметри робочого каталогу перелічені у vim.wikia.com/wiki/Set_working_directory_to_the_current_file .
studgeek

30

Скажімо, у нас така проста проектна структура:

введіть тут опис зображення

привітання.txt виглядає так

введіть тут опис зображення

а так виглядає інформація / age.txt

введіть тут опис зображення

Скажімо, ми хочемо замінити всі випадки Сема на Боба. Ось що ми зробили:

  1. Встановити робочий каталог

    Переконайтеся, що поточний робочий каталог Vim є коренем проекту (не покаже, як це зробити тут).

  2. Знайдіть файли, що містять "Sam"

    Використовуйте команду vimgrep Vim для пошуку всіх подій Sam в рамках проекту (зверніть увагу: **/*пошук у всіх файлах рекурсивно)

    :vimgrep /Sam/gj **/*
    

    Цей список заповнить список швидких виправлень усіма примірниками Sam. Якщо ви хочете переглянути список виправлень, ви можете скористатися командою Vim:copen введіть тут опис зображення

  3. Заміна у всіх файлах, що містять "Sam"

    Тепер ми хочемо запустити команду Vim-замінника у кожному файлі зі списку швидких виправлень. Це можна зробити за допомогою :cfdo {cmd}команди, яка виконує {cmd} у кожному файлі у списку швидких виправлень. Конкретний {cmd}, який ми хочемо використовувати, є substituteабо sкоротко. Повна лінія виглядала б так:

    :cfdo %s/Sam/Bob/g
    

    Ви можете додати прапор c, щоб підтвердити всі заміни, якщо вам подобається:

    :cfdo %s/Sam/Bob/gc
    
  4. Збережіть усі файли

    :cfdo update
    

2
Мені це подобається більше. Це просто і працює з Ack (або будь-яким плагіном, який заповнює вікно QuickFix).
Зухайб

1
Це чудова відповідь
Peoplee

2
cfdo %s/Sam/Bob/g | update
Отримував

@hakunin Я рекомендую встановити hiddenпараметр, :set hiddenякщо ви цього ще не зробили.
Ніко Белік

3

Хоча це не рішення VIM, якщо ви використовуєте VI / VIM, вам може бути простіше використовувати рішення CLI. Щоб змінити всі файли в поточному каталозі, використовуйте так, perlяк це було зроблено для таких ситуацій:

$ perl -pi -e 's/foo/bar/g' *

Якщо вам потрібно це зробити і в підкаталогах, я зазвичай парую perlз find:

$ find . -name '*' -print0 | xargs -0 perl -pi -e 's/foo/bar/g'

Приємно в цьому те, що ви можете легко уточнити список до певних типів файлів. Наприклад, для обмеження файлів python:

$ perl -pi -e 's/foo/bar/g' *.py
$ find . -name '*.py' -print0 | xargs -0 perl -pi -e 's/foo/bar/g'

1

Щоб замінити фразу на іншу, можна використовувати режим Vim Ex.

Наприклад ( exпсевдонім до vim -E):

$ ex -s +'bufdo!%s/foo/bar/g' -cxa *.*

Рекурсивно в bash / zsh (з globstarнабором, наприклад shopt -s globstar):

$ ex -s +'bufdo!%s/foo/bar/g' -cxa **/*.*
$ ex -s +'n **/*.*' +'bufdo!%s/foo/bar/g' -cxa

Рекурсивно (використовуючи findта ігноруючи приховані файли, такі як .gitфайли):

$ find . -type f -not -path '*/\.*' -exec ex -s +'bufdo!%s/foo/bar/g' -cxa {} "+"

Примітка: :bufdoКоманда не є POSIX .

Примітка: Синтаксис -not -path '*/\.*'використовується для ігнорування прихованих файлів (наприклад, .git).



0

Ось команда оболонки за допомогою findта exредактора (без використання:bufdo ):

find . -name '*.rb' -exec ex +'%s/foo/bar/ge' -V1 -scwq! {} ';'

Це дозволить редагувати на місці всі *.rbфайли у поточній папці (рекурсивно) та замінювати fooна bar.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.