Tìm kiếm Vim thay thế tất cả các tệp trong thư mục (dự án) hiện tại


36

Một trong những câu hỏi mở mà tôi có về Vim là liệu có cách nào để thực hiện tìm kiếm / thay thế trong dự án hiện tại không (hãy chịu đựng nếu tôi sử dụng khái niệm này được kế thừa từ các biên tập viên khác).

Chẳng hạn, giả sử tôi muốn tìm kiếm các tệp dự án của mình để tìm tên phương thức và đổi tên tất cả các phiên bản của lệnh gọi phương thức đó.

Đây là cách tôi có thể tiến hành với Sublime.

nhập mô tả hình ảnh ở đây

Làm thế nào bạn sẽ làm điều này trong Vim (có thể là MacVim) mà không cần dựa vào các chương trình khác như ackhoặc sed?

Câu trả lời:


35

Có nhiều hướng khác nhau để làm điều đó.

Bên trong thư mục hiện tại

Nếu bạn muốn thực hiện tìm kiếm / thay thế trong cây dự án, bạn có thể sử dụng danh sách đối số của Vim .

Đơn giản chỉ cần mở Vim và sau đó sử dụng :argslệnh để điền danh sách đối số. Bạn có thể vượt qua trong nhiều tên tập tin hoặc thậm chí là ảm đạm.

Ví dụ, :args **/*.rbsẽ tìm kiếm đệ quy thư mục hiện tại cho các tệp ruby. Lưu ý rằng điều này cũng giống như mở Vim với vim **/*.rb. Bạn thậm chí có thể sử dụng findlệnh của shell để lấy danh sách tất cả các tệp trong thư mục hiện tại bằng cách chạy:

:args `find . -type f`

Bạn có thể xem danh sách args hiện tại bằng :argscách tự chạy . Nếu bạn muốn thêm hoặc xóa các tập tin khỏi danh sách, bạn có thể sử dụng :argaddcác :argdeletelệnh tương ứng.

Khi bạn hài lòng với danh sách, bây giờ bạn có thể sử dụng :argdolệnh mạnh mẽ của Vim để chạy lệnh cho mọi tệp trong danh sách đối số::argdo %s/search/replace/g

Dưới đây là một số mẹo để tìm kiếm (dựa trên một số ý kiến):

  1. Sử dụng một ranh giới từ nếu bạn muốn tìm kiếm "foo" nhưng không phải "foo_bar". Sử dụng \<và các \>cấu trúc xung quanh mẫu tìm kiếm như vậy::argdo %s/\<search\>/foobar/g
  2. Sử dụng /ccờ tìm kiếm nếu bạn muốn Vim yêu cầu xác nhận trước khi thay thế cụm từ tìm kiếm.
  3. Sử dụng /ecờ tìm kiếm nếu bạn muốn bỏ qua các lỗi "không tìm thấy mẫu".
  4. Bạn cũng có thể chọn lưu tệp sau khi thực hiện tìm kiếm : :argdo %s/search/replace/g | update. Ở đây, :updateđược sử dụng bởi vì nó sẽ chỉ lưu tệp nếu nó đã thay đổi.

Mở bộ đệm

Nếu bạn đã mở bộ đệm, bạn muốn thực hiện tìm kiếm / thay thế, bạn có thể sử dụng :bufdo, nó chạy một lệnh cho mọi tệp trong danh sách bộ đệm của bạn ( :ls).

Lệnh này rất giống với :argdo: :bufdo %s/search/replace/g

Tương tự :argdo:bufdo, có :windo:tabdohành động tương ứng trên các cửa sổ và tab. Chúng ít được sử dụng nhưng vẫn hữu ích để biết.


4
Nó có thể là một ý tưởng tốt để sử dụng /ccờ để xác nhận thay thế.
romainl

3
Tôi cũng sẽ khuyên bạn nên sử dụng ranh giới từ \<\>xung quanh searchđể tránh thay thế một phần từ.
tommcdo

1
Một nhận xét khác là thư mục làm việc của vim theo mặc định nơi bạn bắt đầu vim, không phải thư mục của tệp hiện tại. Bạn có thể đặt thư mục làm việc cho tập tin hiện tại bằng cách sử dụng :cd %:p:h. Các tùy chọn thư mục làm việc khác được liệt kê trong vim.wikia.com/wiki/set_usiness_directory_to_the_cản_file .
studgeek

29

Giả sử chúng ta có một cấu trúc dự án đơn giản như thế này:

nhập mô tả hình ảnh ở đây

hello.txt trông giống như

nhập mô tả hình ảnh ở đây

và thông tin / age.txt trông giống như

nhập mô tả hình ảnh ở đây

Hãy nói rằng chúng tôi muốn thay thế tất cả các lần xuất hiện của Sam bằng Bob. Đây là những gì chúng ta sẽ làm:

  1. Đặt thư mục làm việc

    Hãy chắc chắn rằng thư mục làm việc hiện tại của Vim là gốc của dự án (sẽ không chỉ cho bạn cách làm điều này ở đây).

  2. Tìm tệp có chứa 'Sam'

    Sử dụng lệnh vimgrep của Vim để tìm kiếm tất cả các lần xuất hiện của Sam trong dự án (lưu ý: các **/*tìm kiếm trong tất cả các tệp đệ quy)

    :vimgrep /Sam/gj **/*
    

    Điều này sẽ điền vào danh sách quickfix với tất cả các phiên bản của Sam. Nếu bạn muốn xem danh sách quickfix, bạn có thể sử dụng lệnh Vim:copen nhập mô tả hình ảnh ở đây

  3. Thay thế trong tất cả các tệp có chứa 'Sam'

    Bây giờ chúng tôi muốn chạy lệnh thay thế của Vim bên trong mỗi tệp trong danh sách quickfix. Chúng ta có thể làm điều này bằng cách sử dụng :cfdo {cmd}lệnh thực thi {cmd} trong mỗi tệp trong danh sách quickfix. {Cmd} cụ thể mà chúng tôi muốn sử dụng là substitutehoặc sviết tắt. Dòng đầy đủ sẽ trông như:

    :cfdo %s/Sam/Bob/g
    

    Bạn có thể thêm cờ c để xác nhận tất cả các thay thế nếu bạn muốn:

    :cfdo %s/Sam/Bob/gc
    
  4. Lưu tất cả các tập tin

    :cfdo update
    

2
Tôi thích điều này hơn. Thật đơn giản và hoạt động với Ack (hoặc bất kỳ plugin nào điền vào cửa sổ QuickFix).
Zuhaib

1
Đây là một câu trả lời tuyệt vời
Peoplee 7/12/2016

2
Đã nhận được "không viết từ thay đổi cuối cùng", đã cfdo %s/Sam/Bob/g | updatesửa nó cho tôi
hakunin

@hakunin Tôi khuyên bạn nên thiết lập hiddentùy chọn :set hiddennếu bạn chưa làm như vậy.
Niko Bellic

3

Mặc dù không phải là giải pháp VIM, nhưng nếu bạn đang sử dụng VI / VIM, bạn có thể thấy sử dụng giải pháp CLI dễ dàng hơn. Để thay đổi tất cả các tệp trong thư mục hiện tại, hãy sử dụng perlnhư được tạo cho các tình huống như thế này:

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

Nếu bạn cũng cần làm điều đó trong các thư mục con, tôi thường ghép perlvới find:

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

Điều tuyệt vời ở đây là bạn có thể dễ dàng tinh chỉnh thêm danh sách cho các loại tệp cụ thể. Ví dụ: để hạn chế các tệp python:

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

1

Để thay thế cụm từ bằng một cụm từ khác, bạn có thể sử dụng chế độ Vim Ex.

Ví dụ ( exlà bí danh vim -E):

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

Đệ quy trong bash / zsh (có globstarbộ, vd shopt -s globstar):

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

Đệ quy (sử dụng findvà bỏ qua các tệp ẩn như .gittệp):

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

Lưu ý: :bufdoLệnh không phải là POSIX .

Lưu ý: Cú pháp -not -path '*/\.*'được sử dụng để bỏ qua các tệp ẩn (chẳng hạn như .git).



0

Đây là lệnh shell sử dụng findextrình soạn thảo (không sử dụng:bufdo ):

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

Điều này sẽ chỉnh sửa tại chỗ tất cả *.rbcác tệp trong thư mục hiện tại (đệ quy) và thay thế foobằng bar.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.