Wyszukiwanie w Vimie zastępuje wszystkie pliki w bieżącym folderze (projektu)

37

Jedno z otwartych pytań na temat Vima dotyczy tego, czy istnieje sposób na wyszukiwanie / zamianę w bieżącym projekcie (proszę o wyrozumiałość, jeśli użyję tego pojęcia odziedziczonego po innych redaktorach).

Załóżmy na przykład, że chcę przeszukać moje pliki projektu w poszukiwaniu nazwy metody i zmienić nazwy wszystkich instancji tego wywołania metody.

W ten sposób mogę kontynuować Sublime.

wprowadź opis zdjęcia tutaj

Jak zrobiłbyś to w Vimie (prawdopodobnie MacVim) bez polegania na innych programach, takich jak acklub sed?

Simone Carletti
źródło

Odpowiedzi:

35

Można to zrobić na kilka sposobów.

Wewnątrz bieżącego katalogu

Jeśli chcesz przeprowadzić wyszukiwanie / zamianę w drzewie projektu, możesz użyć listy argumentów Vima .

Po prostu otwórz Vima, a następnie użyj :argspolecenia, aby wypełnić listę argumentów. Możesz przekazać wiele nazw plików, a nawet globów.

Na przykład :args **/*.rbbędzie rekurencyjnie przeszukiwał bieżący katalog w poszukiwaniu plików ruby. Zauważ, że jest to również otwarcie Vima za pomocą vim **/*.rb. Możesz nawet użyć polecenia powłoki, findaby uzyskać listę wszystkich plików w bieżącym katalogu, uruchamiając:

:args `find . -type f`

Możesz wyświetlić bieżącą listę argumentów, uruchamiając :argssię samodzielnie. Jeśli chcesz dodać lub usunąć pliki z listy, można użyć :argaddalbo z :argdeletepolecenia odpowiednio.

Gdy jesteś zadowolony z listy, możesz teraz użyć potężnego :argdopolecenia Vima, które uruchamia polecenie dla każdego pliku na liście argumentów::argdo %s/search/replace/g

Oto kilka wskazówek dotyczących wyszukiwania (na podstawie niektórych komentarzy):

  1. Użyj granicy słowa, jeśli chcesz wyszukać „foo”, ale nie „foo_bar”. Użyj konstrukcji \<i \>wokół wzorca wyszukiwania w następujący sposób::argdo %s/\<search\>/foobar/g
  2. Użyj /cflagi wyszukiwania, jeśli chcesz, aby Vim poprosił o potwierdzenie przed zamianą wyszukiwanego hasła.
  3. Użyj /eflagi wyszukiwania, jeśli chcesz pominąć błędy „wzorzec nie znaleziony”.
  4. Można również zdecydować się na zapisanie pliku po wykonaniu wyszukiwania: :argdo %s/search/replace/g | update. Tutaj :updatejest używany, ponieważ zapisze plik tylko, jeśli został zmieniony.

Otwórz bufory

Jeśli masz już otwarte bufory, które chcesz przeszukać / zamienić, możesz użyć :bufdo, który uruchamia polecenie dla każdego pliku na liście buforów ( :ls).

Polecenie jest bardzo podobne do :argdo: :bufdo %s/search/replace/g

Podobnie jak :argdoi :bufdoistnieje :windoi :tabdodziała odpowiednio na okna i karty. Są rzadziej używane, ale nadal warto je znać.

akshay
źródło
4
Dobrym pomysłem może być użycie /cflagi do potwierdzenia zamiany.
romainl
3
Poleciłbym również stosowanie granic słów \<i \>ich searchunikanie, aby uniknąć częściowej zamiany słów.
tommcdo
1
Innym komentarzem jest to, że katalog roboczy vima jest domyślnie tam, gdzie go uruchomiłeś, a nie katalog bieżącego pliku. Możesz ustawić katalog roboczy na bieżący plik za pomocą :cd %:p:h. Inne opcje katalogu roboczego są wymienione w vim.wikia.com/wiki/Set_working_directory_to_the_current_file .
studgeek
30

Powiedzmy, że mamy prostą strukturę projektu:

wprowadź opis zdjęcia tutaj

pozdrowienia.txt wygląda

wprowadź opis zdjęcia tutaj

i wygląda na info / age.txt

wprowadź opis zdjęcia tutaj

Powiedzmy, że chcemy zastąpić wszystkie wystąpienia Sama Bobem. Oto, co byśmy zrobili:

  1. Ustaw katalog roboczy

    Upewnij się, że bieżący katalog roboczy Vima jest katalogiem głównym projektu (nie pokażę ci, jak to zrobić tutaj).

  2. Znajdź pliki zawierające „Sam”

    Użyj komendy vimgrep Vima, aby wyszukać wszystkie wystąpienia Sama w projekcie (uwaga: **/*rekursywnie wyszukiwania we wszystkich plikach)

    :vimgrep /Sam/gj **/*
    

    Spowoduje to zapełnienie listy poprawek wszystkimi instancjami Sama. Jeśli chcesz wyświetlić listę poprawek, możesz użyć polecenia Vim:copen wprowadź opis zdjęcia tutaj

  3. Zastępuj we wszystkich plikach zawierających „Sam”

    Teraz chcemy uruchomić polecenie zastępcze Vima w każdym pliku na liście szybkich poprawek. Możemy to zrobić za pomocą :cfdo {cmd}polecenia, które wykonuje {cmd} w każdym pliku na liście szybkich poprawek. Specyficzny {cmd} Chcemy wykorzystać to substitutealbo sza krótki. Pełna linia wyglądałaby następująco:

    :cfdo %s/Sam/Bob/g
    

    Możesz dodać flagę c, aby potwierdzić wszystkie zamiany, jeśli chcesz:

    :cfdo %s/Sam/Bob/gc
    
  4. Zapisz wszystkie pliki

    :cfdo update
    
Niko Bellic
źródło
2
Bardziej mi się to podoba. Jest to proste i działa z Ack (lub dowolną wtyczką, która zapełnia okno QuickFix).
Zuhaib,
1
To świetna odpowiedź
Peoplee
2
cfdo %s/Sam/Bob/g | update
Dostałem
@hakunin Polecam ustawienie hiddenopcji, :set hiddenjeśli jeszcze tego nie zrobiłeś.
Niko Bellic
3

Chociaż nie jest to rozwiązanie VIM, jeśli używasz VI / VIM, łatwiejsze może być użycie rozwiązania CLI. Aby zmienić wszystkie pliki w bieżącym katalogu, użyj tego, perlco zostało zrobione dla takich sytuacji:

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

Jeśli musisz to zrobić również w podkatalogach, zwykle łączę się perlz find:

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

Zaletą tego jest to, że możesz łatwo zawęzić listę do określonych typów plików. Na przykład, aby ograniczyć się do plików python:

$ perl -pi -e 's/foo/bar/g' *.py
$ find . -name '*.py' -print0 | xargs -0 perl -pi -e 's/foo/bar/g'
dotancohen
źródło
1

Aby zamienić frazę na inną, możesz użyć trybu Vim Ex.

Na przykład ( exjest alias do vim -E):

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

Rekurencyjnie w bash / zsh (z globstarzestawem, np. shopt -s globstar):

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

Rekurencyjnie (używając findi ignoruj ​​ukryte pliki, takie jak .gitpliki):

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

Uwaga: :bufdoPolecenie to nie POSIX .

Uwaga: Składnia -not -path '*/\.*'służy do ignorowania ukrytych plików (takich jak .git).

kenorb
źródło
uwaga bufdo nie jest POSIX pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html
Steven Penny
0

Oto polecenie powłoki przy użyciu findi exedytora (bez użycia:bufdo ):

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

Będzie to edycja na miejscu wszystkie *.rbpliki w bieżącym katalogu (rekurencyjnie) i wymienić fooz bar.

kenorb
źródło