Tìm và thay thế các chuỗi trong vim trên nhiều dòng


352

Tôi có thể làm :%s/<search_string>/<replace_string>/gđể thay thế một chuỗi trên một tệp hoặc :s/<search_string>/<replace_string>/để thay thế trong dòng hiện tại.

Làm cách nào tôi có thể chọn và thay thế các từ trong các dòng chọn lọc trong vim?

Ví dụ: thay thế văn bản từ các dòng 6-10, 14-18nhưng không phải từ 11-13.



Câu trả lời:


254

Các :&&lệnh lặp đi lặp lại sự thay thế cuối cùng với những lá cờ như vậy. Bạn có thể cung cấp (các) phạm vi bổ sung cho nó (và ghép bao nhiêu tùy thích):

:6,10s/<search_string>/<replace_string>/g | 14,18&&

Nếu bạn có nhiều phạm vi , tôi muốn sử dụng một vòng lặp:

:for range in split('6,10 14,18')| exe range 's/<search_string>/<replace_string>/g' | endfor

5
Cảm ơn. Lưu ý cho người dùng trong tương lai - :6,10s/<search_string>/<replace_string>/g | :14,18&& | :20,23&& | :28,31&&cũng sẽ hoạt động, forvòng lặp giúp dễ nhớ và thực thi hơn.
mu

5
Vui vì bạn thích nó! Các :lệnh tiếp theo là tùy chọn, btw, vì vậy bạn có thể lưu thêm một số tổ hợp phím.
Ingo Karkat

2
:&&sẽ tiết kiệm cho tôi hàng trăm tổ hợp phím mỗi tuần. Cảm ơn!
pdoherty926

Nó hoạt động mà không có 'g' ở cuối vim của tôi. Vì vậy, có thể khi bạn chỉ định phạm vi dòng, nó không cần cờ toàn cầu
Tayyar R

3
@TayyarR Phạm vi bao gồm các dòng (theo chiều dọc, có thể nói), trong khi cờ 'g' xác định chỉ một hoặc tất cả các kết quả khớp trong dòng (theo chiều ngang) được thay thế.
Ingo Karkat

385

Thay thế tất cả:

:%s/foo/bar/g

Tìm từng lần xuất hiện của 'foo' (trong tất cả các dòng) và thay thế nó bằng 'bar'.

Đối với các dòng cụ thể:

:6,10s/foo/bar/g

Thay đổi từng 'foo' thành 'bar' cho tất cả các dòng từ dòng 6 đến dòng 10.


3
mục đích của / g ở đây là gì? Xin lỗi tôi mới dùng linux
Raja Anbazhagan

4
@RajaAnbazhagan Phần cuối cùng của biểu thức này, sau phần cuối cùng /, là nơi bạn chỉ ra các cờ cho hoạt động. Lệnh này thường sẽ thay thế trận đấu đầu tiên trên một dòng; Với gcờ nó sẽ thay thế tất cả các lần xuất hiện.
Lít

17
Bạn thực sự nên tham khảo các nguồn của mình (ví dụ: vim.wikia.com/wiki/Search_and_Vplace), nếu bạn định sao chép và qua công việc của người khác.
Andrew S

2
Các %điều làm công việc! Mặt khác, nó chỉ là lần đầu tiên xuất hiện.
Santosh Kumar

7
%=> chạy lệnh này trên tất cả các dòng. g=> khớp nhiều lần xuất hiện trong cùng một dòng.
Shaahiin

55

Là một lưu ý phụ, thay vì phải nhập số dòng, chỉ cần tô sáng các dòng bạn muốn tìm / thay thế trong một trong các chế độ trực quan:

  • VISUALchế độ ( V)
  • VISUAL BLOCKchế độ ( Ctrl+ V)
  • VISUAL LINEchế độ ( Shift+ V, hoạt động tốt nhất trong trường hợp của bạn)

Khi bạn đã chọn các dòng để thay thế, hãy nhập lệnh của bạn:

:s/<search_string>/<replace_string>/g

Bạn sẽ lưu ý rằng phạm vi '<,'>sẽ được chèn tự động cho bạn:

:'<,'>s/<search_string>/<replace_string>/g

Ở đây '<chỉ đơn giản có nghĩa là dòng được tô sáng đầu tiên , và '>có nghĩa là dòng được tô sáng cuối cùng .

Lưu ý rằng hành vi có thể bất ngờ khi ở NORMALchế độ: '<'>trỏ đến điểm bắt đầu và kết thúc của phần tô sáng cuối cùng được thực hiện ở một trong các VISUALchế độ. Thay vào đó, trong NORMALchế độ, số dòng đặc biệt .có thể được sử dụng, có nghĩa đơn giản là dòng hiện tại . Do đó, bạn chỉ có thể tìm / thay thế trên dòng hiện tại như thế này:

:.s/<search_string>/<replace_string>/g

Một điều cần lưu ý là việc chèn một giây :giữa phạm vi và lệnh find / thay thế không gây hại, nói cách khác, các lệnh này sẽ vẫn hoạt động:

:'<,'>:s/<search_string>/<replace_string>/g
:.:s/<search_string>/<replace_string>/g

1
> Ví dụ: thay thế văn bản từ các dòng 6-10, 14-18 nhưng không phải từ 11-13. - không trả lời của bạn trả lời câu hỏi này, phải không?
poige

27

Bạn có thể làm điều đó với hai chuỗi tìm / thay thế

  :6,10s/<search_string>/<replace_string>/g
  :14,18s/<search_string>/<replace_string>/g

Lần thứ hai tất cả những gì bạn cần điều chỉnh là phạm vi, vì vậy thay vì gõ tất cả, tôi sẽ nhớ lại lệnh cuối cùng và chỉ chỉnh sửa phạm vi


20

Trong vim nếu bạn bối rối tất cả các dòng sẽ bị ảnh hưởng, Sử dụng bên dưới

 :%s/foo/bar/gc  

Thay đổi mỗi 'foo' thành 'bar', nhưng yêu cầu xác nhận trước. Nhấn 'y' cho có và 'n' cho không. Đừng quên lưu lại sau đó

:wq

1
Bạn thực sự có thể sử dụng ccờ ngoài việc chỉ định phạm vi, do đó, :6,10s/<search_string>/<replace_string>/choạt động. clà viết tắt củaconfirm . Tôi sử dụng ccờ khá thường xuyên để tránh vô tình thay thế những từ mà tôi không nghĩ về việc chúng tồn tại ở đó.
Wolfson

16

VI tìm kiếm và thay thế các ví dụ lệnh

Hãy để chúng tôi nói rằng bạn muốn tìm một từ có tên là foo foo và thay thế bằng thanh bar.

[Esc]Phím nhấn đầu tiên

%s/foo/bar/Nhập : (dấu hai chấm) theo sau và nhấn phím [Enter]

:%s/foo/bar/


11
:%s/<search_string>/<replace_string>/gLệnh của bạn sẽ thay thế tất cả các lần xuất hiện trong toàn bộ tập tin. Không chính xác câu trả lời cho câu hỏi, nhưng dù sao cũng hữu ích :)
tanius 16/2/2017

@tanius Thật ra đó là câu trả lời thẳng thắn nhất cho vấn đề của tôi. Bạn có thể xem xét sửa đổi câu hỏi thành "Tìm và thay thế chuỗi trong vim trên dòng" Đã chọn "
Omid N

9

Chúng tôi không cần phải nhập số dòng hiện tại.

Nếu bạn muốn thay đổi từng foođể barcho dòng hiện tại ( .) và hai dòng tiếp theo ( +2), chỉ cần làm:

:.,+2s/foo/bar/g

Nếu bạn muốn xác nhận trước khi thay đổi được thực hiện, hãy thay thế gbằng gc:

:.,+2s/foo/bar/gc

Một điều thú vị khác mà tôi thường sử dụng là :.,$s/foo/bar/gctìm kiếm & thay thế bắt đầu từ dòng hiện tại cho đến cuối tập tin.
Wolfson

3

Tìm kiếm và thay thế

:%s/search\|search2\|search3/replace/gci

g => tìm kiếm toàn cầu

c => Yêu cầu xác nhận trước

i => Trường hợp không nhạy cảm

Nếu bạn muốn thay thế trực tiếp mà không cần xác nhận, sử dụng lệnh dưới đây

:%s/search/replace/g

Nếu bạn muốn xác nhận cho từng thay thế thì hãy chạy lệnh dưới đây

:%s/search/replace/gc

Yêu cầu xác nhận trước, ở đây tìm kiếm sẽ không phân biệt chữ hoa chữ thường.

:%s/search/replace/gci

1

Chỉ định phạm vi thông qua lựa chọn trực quan là được nhưng khi có các thao tác rất đơn giản chỉ qua một vài dòng có thể được chọn bởi một toán tử thì tốt nhất là áp dụng các lệnh này làm toán tử.

Điều đáng buồn này không thể được thực hiện thông qua các lệnh vim tiêu chuẩn. Bạn có thể làm một cách giải quyết bằng cách sử dụng! toán tử (bộ lọc) và bất kỳ đối tượng văn bản. Ví dụ: để áp dụng thao tác cho một đoạn văn, bạn có thể làm:

!ip

Điều này phải được đọc là "Áp dụng toán tử! Trong một đoạn". Toán tử bộ lọc bắt đầu chế độ lệnh và tự động chèn phạm vi các dòng theo sau là "!" mà bạn có thể xóa ngay sau đó. Nếu bạn áp dụng điều này, cho đoạn văn sau:

1
2  Repellendus qui velit vel ullam!
3  ipsam sint modi! velit ipsam sint
4  modi! Debitis dolorum distinctio
5  mollitia vel ullam! Repellendus qui
6  Debitis dolorum distinctio mollitia
7  vel ullam! ipsam
8
9  More text around here

Kết quả sau khi nhấn "! Ap" sẽ như sau:

:.,.+5

Là '.' (điểm) có nghĩa là dòng hiện tại, phạm vi giữa dòng hiện tại và 5 dòng sau sẽ được sử dụng cho hoạt động. Bây giờ bạn có thể thêm lệnh thay thế theo cách tương tự như trước đây.

Phần xấu là điều này không dễ dàng hơn khi chọn văn bản để áp dụng toán tử sau này. Phần tốt là điều này có thể lặp lại việc chèn phạm vi cho các phạm vi văn bản tương tự khác (trong trường hợp này là các đoạn) với kích thước khác nhau rõ rệt. Tức là, nếu sau này bạn muốn chọn phạm vi lớn hơn đoạn '.' sẽ cho nó đúng.

Ngoài ra, nếu bạn thích ý tưởng sử dụng các đối tượng văn bản ngữ nghĩa để chọn phạm vi hoạt động, bạn có thể kiểm tra plugin EXtend.vim của tôi có thể làm tương tự nhưng theo cách dễ dàng hơn.


0

Để trả lời câu hỏi này:

:40,50s/foo/bar/g

thay thế foo bằng thanh trong các dòng này giữa dòng thứ 40 và dòng thứ 50 (đã bao gồm), khi thực hiện lệnh này, bạn hiện có thể ở bất kỳ dòng nào.

:50,40s/foo/bar/g

cũng hoạt động, vim sẽ yêu cầu bạn xác nhận và sau đó thực hiện thay thế cho bạn như thể bạn đã nhập lệnh đầu tiên.

:,50s/foo/bar/g

thay thế foo bằng thanh trong các dòng này giữa dòng bạn hiện đang ở và dòng thứ 50 (đã bao gồm). (nếu bạn đang ở trong một dòng SAU thì vim dòng thứ 50 sẽ yêu cầu xác nhận lại)

Để làm rõ sự khác biệt giữa vim và plugin vrapper của Eclipse:

Lưu ý rằng trong varpper

:,50s/foo/bar/g lệnh sẽ KHÔNG hoạt động.

:50,40s/foo/bar/g sẽ làm việc mà không yêu cầu xác nhận.

(Dành cho phiên bản Vrapper 0.74.0 trở lên).


-5
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal
/sys/sim/source/gm/kg/jl/ls/owow/lsal

Giả sử nếu bạn muốn thay thế ở trên với một số thông tin khác.

COMMAND(:%s/\/sys\/sim\/source\/gm\/kg\/jl\/ls\/owow\/lsal/sys.pkg.mpu.umc.kdk./g)

Trong phần này, phần trên sẽ được thay thế bằng ( sys.pkg.mpu.umc.kdk.).


Tôi không chắc điều này thực sự trả lời câu hỏi. Từ câu hỏi, có vẻ như người hỏi đã biết cách sử dụng %sđể sửa đổi đầu vào nhưng muốn biết cách thực hiện "bán toàn cầu" (nghĩa là thông số kỹ thuật của anh ta là các dòng 6-10 và 14-18 nhưng không phải trên các dòng 11- 13).
Brandon Buck

1
Ngoài ra "LỰA CHỌN" là gì? Và bạn đang bị hội chứng tăm nghiêng .
Martin Tournoij

Để chữa trị hội chứng đó, bạn có thể sử dụng nhân vật khác như delimiter thay vì mặc định /, ví dụ như !, @, _::%s_/sys/sim/source/gm/kg/jl/ls/owow/lsal_sys.pkg.mpu.umc.kdk_g
MortezaE
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.