Vim search mengganti semua file dalam folder (proyek) saat ini


37

Salah satu pertanyaan terbuka yang saya miliki tentang Vim adalah apakah ada cara untuk melakukan pencarian / penggantian dalam proyek saat ini (bersabarlah jika saya menggunakan gagasan ini yang diwarisi dari editor lain).

Sebagai contoh, mari kita asumsikan saya ingin mencari file proyek saya untuk nama metode, dan mengganti nama semua instance dari panggilan metode itu.

Ini adalah bagaimana saya dapat melanjutkan dengan Sublime.

masukkan deskripsi gambar di sini

Bagaimana Anda melakukan ini di Vim (mungkin MacVim) tanpa mengandalkan program lain seperti ackatau sed?

Jawaban:


35

Ada beberapa cara untuk melakukan ini.

Di dalam Direktori Saat Ini

Jika Anda ingin melakukan pencarian / ganti di pohon proyek, Anda dapat menggunakan daftar argumen Vim .

Cukup buka Vim dan kemudian gunakan :argsperintah untuk mengisi daftar argumen. Anda dapat memasukkan beberapa nama file atau bahkan gumpalan.

Sebagai contoh, :args **/*.rbsecara rekursif akan mencari direktori file ruby ​​saat ini. Perhatikan bahwa ini juga seperti membuka Vim dengan vim **/*.rb. Anda bahkan dapat menggunakan perintah shell finduntuk mendapatkan daftar semua file di direktori saat ini dengan menjalankan:

:args `find . -type f`

Anda dapat melihat daftar args saat ini dengan menjalankannya :argssendiri. Jika Anda ingin menambah atau menghapus file dari daftar, Anda dapat menggunakan perintah :argaddatau :argdeletemasing-masing.

Setelah Anda puas dengan daftar tersebut, sekarang Anda dapat menggunakan :argdoperintah Vim yang kuat yang menjalankan perintah untuk setiap file dalam daftar argumen::argdo %s/search/replace/g

Berikut ini beberapa kiat untuk mencari (berdasarkan beberapa komentar):

  1. Gunakan batas kata jika Anda ingin mencari "foo" tetapi bukan "foo_bar". Gunakan \<dan \>susun di sekitar pola pencarian seperti::argdo %s/\<search\>/foobar/g
  2. Gunakan /cbendera pencarian jika Anda ingin Vim meminta konfirmasi sebelum mengganti istilah pencarian.
  3. Gunakan /ebendera pencarian jika Anda ingin melewati kesalahan "pola tidak ditemukan".
  4. Anda juga dapat memilih untuk menyimpan file setelah melakukan pencarian: :argdo %s/search/replace/g | update. Di sini, :updatedigunakan karena hanya akan menyimpan file jika sudah berubah.

Buka buffer

Jika Anda sudah memiliki buffer terbuka yang ingin Anda lakukan pencarian / ganti, Anda dapat menggunakan :bufdo, yang menjalankan perintah untuk setiap file dalam daftar buffer Anda ( :ls).

Perintahnya sangat mirip dengan :argdo: :bufdo %s/search/replace/g

Mirip dengan :argdodan :bufdo, ada :windodan :tabdoyang bertindak masing-masing pada windows dan tab. Mereka lebih jarang digunakan tetapi masih berguna untuk diketahui.


4
Mungkin bisa menjadi ide yang baik untuk menggunakan /cbendera untuk mengkonfirmasi penggantian.
romainl

3
Saya juga akan merekomendasikan menggunakan batas kata \<dan \>sekitar searchuntuk menghindari penggantian kata parsial.
tommcdo

1
Satu komentar lain adalah direktori kerja vim secara default di mana Anda memulai vim, bukan direktori file saat ini. Anda dapat mengatur direktori kerja ke file saat ini menggunakan :cd %:p:h. Opsi direktori kerja lainnya tercantum di vim.wikia.com/wiki/Set_working_directory_to_the_current_file .
Studgeek

30

Katakanlah kita memiliki struktur proyek sederhana seperti ini:

masukkan deskripsi gambar di sini

greeting.txt terlihat seperti

masukkan deskripsi gambar di sini

dan info / age.txt terlihat seperti

masukkan deskripsi gambar di sini

Katakanlah kita ingin mengganti semua kejadian Sam dengan Bob. Inilah yang akan kami lakukan:

  1. Atur direktori kerja

    Pastikan direktori kerja Vim saat ini adalah root dari proyek (tidak akan menunjukkan kepada Anda bagaimana melakukan ini di sini).

  2. Temukan file yang mengandung 'Sam'

    Gunakan perintah vimgrep Vim untuk mencari semua kejadian Sam dalam proyek (catatan: **/*pencarian di semua file secara rekursif)

    :vimgrep /Sam/gj **/*
    

    Ini akan mengisi daftar perbaikan cepat dengan semua instance Sam. Jika Anda ingin melihat daftar perbaikan cepat, Anda dapat menggunakan perintah Vim:copen masukkan deskripsi gambar di sini

  3. Pengganti dalam semua file yang mengandung 'Sam'

    Sekarang kami ingin menjalankan perintah pengganti Vim di dalam setiap file dalam daftar perbaikan cepat. Kita dapat melakukan ini menggunakan :cfdo {cmd}perintah yang mengeksekusi {cmd} di setiap file dalam daftar perbaikan cepat. {Cmd} spesifik yang ingin kita gunakan adalah substituteatau ssingkatnya. Baris penuh akan terlihat seperti:

    :cfdo %s/Sam/Bob/g
    

    Anda dapat menambahkan tanda c untuk mengonfirmasi semua penggantian jika Anda suka:

    :cfdo %s/Sam/Bob/gc
    
  4. Simpan semua file

    :cfdo update
    

2
Saya lebih suka ini. Ini sederhana, dan berfungsi dengan Ack (atau plugin apa pun yang mengisi jendela QuickFix).
Zuhaib

1
Ini adalah jawaban yang bagus
Peoplee

2
Sudah "tidak menulis sejak perubahan terakhir", melakukan cfdo %s/Sam/Bob/g | updatememperbaikinya untuk saya
hakunin

@ Hakunin Saya akan merekomendasikan pengaturan hiddenopsi dengan :set hiddenjika Anda belum melakukannya.
Niko Bellic

3

Meskipun bukan solusi VIM, jika Anda menggunakan VI / VIM Anda mungkin merasa lebih mudah untuk menggunakan solusi CLI. Untuk mengubah semua file di direktori saat ini, gunakan perlseperti yang dibuat untuk situasi seperti ini:

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

Jika Anda perlu melakukannya di subdirektori juga, saya biasanya memasangkan perldengan find:

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

Yang menyenangkan tentang ini adalah Anda dapat dengan mudah memperbaiki daftar ke tipe file tertentu. Misalnya, untuk membatasi ke file python:

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

1

Untuk mengganti frase dengan yang lain, Anda dapat menggunakan mode Vim Ex.

Misalnya ( exalias untuk vim -E):

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

Secara rekursif dalam bash / zsh (dengan globstarset, misalnya shopt -s globstar):

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

Secara rekursif (menggunakan finddan mengabaikan file tersembunyi seperti .gitfile):

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

Catatan: :bufdoPerintah ini bukan POSIX .

Catatan: Sintaks -not -path '*/\.*'digunakan untuk mengabaikan file tersembunyi (seperti .git).



0

Berikut adalah perintah shell using finddan exeditor (tanpa menggunakan:bufdo ):

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

Ini akan mengedit semua *.rbfile di dalam folder saat ini (secara rekursif) dan menggantinya foodengan bar.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.