Tìm kiếm đơn giản và thay thế như Notepad?
Tôi biết về substitutelệnh và cách sử dụng nó như một lệnh cũ:%s/<old>/<new>/g
Tuy nhiên, khi <new>chứa một chuỗi rất phức tạp, ví dụ một URL phức tạp với nhiều ký tự như % [ ] : / \v.v., thì các ký tự bắt đầu là một phần của lệnh (đặc biệt là /hoặc :) và tôi phải bắt đầu sử dụng các chuỗi thoát, tức là\
Có cách nào để tắt tất cả nhu cầu thoát và tất cả thông dịch, để tôi có thể thay thế <old>bằng <new>ngay cả khi <old>và <new>có các ký tự ASCII tùy ý, bao gồm cả / : [ ] % # $ ( )v.v. không?
Hiện tại tôi sử dụng Notepad để làm điều này, nhưng tôi hy vọng tôi có thể ở lại VIM.
Trả lời
Vâng, giả sử mẫu không chứa \thì điều này sẽ hoạt động:
:%s/\Vpattern/\='string'
Trong mọi trường hợp, khi mẫu & chuỗi thay thế nằm trong các biến, điều này sẽ hoạt động:
let pattern='<old>'
let str='<new>'
:exec "s/\\V" . escape(escape( pattern, '\'),'/') . "/\\=str"
tất nhiên, bạn có thể sử dụng các phương thức khác nhau như input()hoặc lệnh args để đặt các biến.
Sau khi đọc các bình luận về câu trả lời đầu tiên của tôi, tôi nhận ra có lẽ có một giải pháp rất đơn giản khác rất nhiều so với gợi ý đầu tiên của tôi. Đề xuất mới này thỉnh thoảng vẫn yêu cầu sử dụng '.' như một công cụ hỗ trợ để đối sánh các ký tự đặc biệt, nhưng vì không có khả năng thực sự để tìm kiếm các chuỗi theo nghĩa đen trong vim, bạn sẽ phải thỏa hiệp theo một số cách. Có những chức năng chuyên biệt bạn có thể tạo có thể phù hợp với bạn. Nhưng tôi thấy giải pháp này rất đơn giản để thực hiện và rất đơn giản để sử dụng.
[vì giải pháp này hầu như không có điểm chung nào với giải pháp đầu tiên của tôi, tôi đăng nó như một câu trả lời thứ hai chứ không phải là một bản chỉnh sửa cho câu trả lời đầu tiên của tôi. Nếu tôi chỉnh sửa toàn bộ câu trả lời, một số nhận xét hữu ích do các thành viên khác thêm vào sẽ không còn ý nghĩa nữa]
Đề xuất mới của tôi như sau ..
Đầu tiên, tôi đặt cái này trong .vimrc ...
set incsearch
Từ :h incsearch...
While typing a search command, show where the pattern, as it was typed
so far, matches. The matched string is highlighted. If the pattern
is invalid or not found, nothing is shown.
[Đối với ví dụ bên dưới, giả sử mẫu tìm kiếm của bạn là một phần của lệnh ": global" hoặc ": Replace"]
Nếu bạn muốn khớp với một URL, bạn bắt đầu nhập http:. Khi bạn nhập, hãy lưu ý rằng kết quả phù hợp có thể tiếp theo trong tệp hoặc văn bản đã chọn của bạn được hiển thị và được đánh dấu trên màn hình của bạn. Khi bạn nhập chữ cái đầu tiên 'h', nó có thể đánh dấu chữ 'h' trong từ con voi (nếu con voi có sự xuất hiện đầu tiên của chữ 'h' trong tệp của bạn hoặc trong văn bản hiện được chọn)
Khi bạn nhập ký tự thứ hai ('t'), chuỗi tìm kiếm của bạn bây giờ là 'ht' và tiêu điểm được đánh dấu sẽ di chuyển trước kết quả khớp đầu tiên của 'ht'. Điều này rất có thể khớp với một URL (không có nhiều từ chứa 'ht'). Nó có thể không phải là URL bạn đang tìm kiếm. Nhưng bạn chưa nhập xong mẫu tìm kiếm của mình.
Vì vậy, bạn tiếp tục nhập. Một 't' ('htt') khác, sau đó là 'p' ('http') và dấu hai chấm ('http:'). Càng xa càng tốt. URL đầu tiên vẫn được đánh dấu trên màn hình của bạn. Nó vẫn có thể không phải là URL bạn muốn, nhưng ít nhất bạn biết mẫu của bạn cho đến nay ( http:) đang hoạt động.
Nhưng ngay sau khi bạn nhập '/', bạn nhận thấy phần đánh dấu không còn theo dõi những gì bạn đang nhập. Đã xảy ra lỗi khi tìm kiếm 'http: /'. Bạn có thể đã quên rằng cần phải thoát '/'.
Nhưng bạn không cần phải nhớ những gì cần được thoát ra !!!
Phản hồi trực tiếp, khi nó không còn khớp với một URL, cho bạn biết ngay lập tức rằng việc thêm '/' vào 'http:' sẽ không phù hợp với bất kỳ thứ gì.
Bạn cần thoát khỏi dấu '/'. Nhưng thay vì thoát khỏi '/', tôi thích nhập một '.' vì nó đơn giản hơn để nhập so với '\ /'. Nhưng bạn có thể gõ '.' hoặc là '\/'
Nhược điểm của phương pháp này là (1) nó không loại bỏ hoàn toàn nhu cầu trốn thoát hoặc '.'; và (2) vị trí màn hình của bạn có khả năng di chuyển qua tệp khi bạn đang nhập mẫu tìm kiếm của mình.
Theo kinh nghiệm của tôi, không ai làm phiền tôi. Bạn có thể tìm thấy khác.
Đối với (1), bạn sẽ biết ngay lập tức khi nhập nội dung cần thoát. Điều này giúp loại bỏ tất cả các phỏng đoán khi tạo một chuỗi tìm kiếm. Tôi thấy nó rất đơn giản và dễ làm việc.
Đối với (2), tôi hiếm khi cần xem vị trí ban đầu của mình trong tệp khi đang nhập chuỗi tìm kiếm. Trên thực tế, chuyển động trực tiếp trước khi khớp mẫu tiếp theo - và phản hồi mà nó cung cấp để xác nhận mẫu tìm kiếm của bạn là hợp lệ - thích hợp hơn nhiều (IMO) hơn là chỉ đơn giản là nhập một chuỗi và hy vọng nó khớp với những gì bạn muốn. Nhưng nếu nhu cầu xem vị trí ban đầu vẫn còn, một màn hình chia đôi đơn giản theo chiều ngang sẽ thực hiện thủ thuật.
.Vimrc của tôi có những dòng này ...
set incsearch
let @o = ".nzz"
map <F8> @o
Các lệnh này cho phép tôi thực hiện tất cả các loại chỉnh sửa mà không phải lo lắng về việc thoát các ký tự đặc biệt dưới bất kỳ hình thức nào. Chúng cũng cho phép tôi dễ dàng thực hiện các chỉnh sửa nhiều dòng.
Khi các lệnh này nằm trong .vimrc của bạn, quy trình sẽ như sau ...
Đầu tiên, bạn phải tìm kiếm một mẫu phù hợp với tất cả các lần xuất hiện mà bạn muốn thay đổi. Điều này quan trọng vì giải pháp của tôi phụ thuộc vào việc chuyển sang lần xuất hiện tiếp theo bằng cách sử dụng toán tử find-next ('n')
Ví dụ: nếu bạn muốn chỉnh sửa tất cả các URL từ máy chủ lưu trữ 'abcxyz.com' có kết thúc bằng .php, bạn có thể tìm kiếm (từ chế độ bình thường) như sau ..
/http:..abcxyz.com.*.php
(... '/' đứng đầu là những gì bạn nhập ở chế độ bình thường để bắt đầu nhập mẫu tìm kiếm. Tôi đã ký tự đại diện '//' trong URL bằng '..' vì tôi không thể nhớ liệu '//' có ảnh hưởng đến hoạt động tìm kiếm. Cái hay là tôi không cần phải nhớ. Miễn là mẫu tìm kiếm của tôi đủ chính xác để nắm bắt tất cả các lần xuất hiện mà tôi cần thay đổi và không khớp với các mẫu tôi không muốn thay đổi, tôi tốt đi)
Sau khi bạn nhấn enter và được định vị ở lần xuất hiện đầu tiên của URL, bạn THỦ CÔNG thay đổi URL đó như mong muốn. Ví dụ: nếu bạn muốn thay đổi tên máy chủ từ 'abcxyz.com' thành 'a111b222.com', bạn có thể thực hiện chỉnh sửa bằng cách nhập ...
'cfzhttp://a111b222'
.. đây chỉ là một trong nhiều cách để chỉnh sửa điều này. Chỉ cần đảm bảo rằng đó là một chỉnh sửa chế độ bình thường, không phải là một chỉnh sửa chế độ lệnh.
Tiếp theo, bạn chuyển sang lần xuất hiện tiếp theo ('n').
Cuối cùng, vẫn ở chế độ bình thường, bạn nhập một số nguyên nào đó vượt quá số lượng thay đổi mà bạn cho rằng cần phải thực hiện. Số nguyên không cần phải chính xác, nó chỉ cần lớn hơn số thay đổi cần thực hiện. Bạn thậm chí có thể sử dụng 100000000000 nếu bạn thực sự không biết cần thực hiện bao nhiêu thay đổi. Nếu chỉ có 20 thay đổi cần thực hiện, macro của tôi sẽ dừng sau lần xuất hiện thứ 20).
Khi bạn đã nhập số nguyên lớn - không nhấn ENTER - nhấn F8 (hoặc bất kỳ phím nào bạn đã gán macro)
Điều này sẽ thay đổi mọi lần xuất hiện của mẫu chính xác như bạn đã làm thủ công cho lần xuất hiện đầu tiên.
Một giả định mà các ánh xạ của tôi giả định là khi bạn nhấn F8 lần đầu tiên, bạn được định vị trong tệp chính xác nơi bạn muốn thực hiện thay đổi đầu tiên.
Điều thú vị về toán tử chỉnh sửa lặp lại trước đó là nó không bị giới hạn trong một loại chỉnh sửa cụ thể. Nó có thể thay đổi 1 ký tự, 1 từ, xuống cuối dòng, đầu dòng, toàn bộ đoạn văn, v.v.
Vì vậy, một lần nữa, ý tưởng là bạn thực hiện thay đổi thủ công của mình một lần - không quan trọng nếu bạn thay đổi một từ, 5 từ, nửa dòng, 7 dòng ... toán tử lặp lại lần sửa cuối ghi nhớ điều này.
Sau đó, bạn tìm kiếm lần xuất hiện tiếp theo để thay đổi, đảm bảo con trỏ ở vị trí thích hợp (ví dụ: nếu bạn đang thay đổi toàn bộ URL, hãy đảm bảo con trỏ ở đầu "http: //" thay vì ở giữa URL) và sau đó nhấn 10000F8.
Thay đổi số nguyên cao hơn nếu bạn có hơn 10.000 lần xuất hiện.
Nhược điểm của điều này là hiệu suất. Nhưng điều đó chỉ trở thành một vấn đề khi bạn có một số lượng lớn các chỉnh sửa cần thực hiện (đối với tôi, hơn 10.000 thay đổi có thể chậm nhưng có thể chấp nhận được. Hơn 100.000 có thể mất một thời gian rất dài và bạn nên hoàn nguyên về: s - nhưng quãng đường của bạn có thể thay đổi)
Một nhược điểm khác, như đã được chỉ ra bởi những người khác, là tôi chưa loại bỏ được các ký tự đại diện, mặc dù tôi đã loại bỏ được các lần thoát. Nhưng tìm ra những gì cần được ký tự đại diện là rất dễ dàng nếu set incsearchnằm trong vimrc của bạn. Tính năng này đánh dấu văn bản phù hợp khi bạn nhập mẫu tìm kiếm của mình. Khi phản hồi trực tiếp ngừng làm nổi bật bất kỳ điều gì, bạn biết mẫu của mình đã sai - thường là do một ký tự cần được loại bỏ. Tôi muốn thay thế ký tự bằng một '.' như một người giữ chỗ cho tất cả (chỉ vì tôi thấy việc nhập đơn giản hơn, nhưng sử dụng một lối thoát cũng được)
Sử dụng cgnvà lặp lại với ..
Đầu tiên, hãy tìm kiếm chuỗi 'cũ' với
/.Tiếp theo, đánh
cgn. Điều này thay thế lần xuất hiện tiếp theo của 'cũ' và đưa bạn vào chế độ chèn.Nhập văn bản thay thế 'mới' và nhấn
Esckhi hoàn tất.Lặp lại, đối với tất cả các lần xuất hiện khác của 'old', với
[count]..
Ý tưởng là nhập chuỗi thay thế 'mới' ở chế độ chèn tốt, để chúng ta không phải lo lắng về việc thoát các ký tự đặc biệt.
Đối với [count], bất kỳ số lượng lớn sẽ đủ; hoặc tìm ra số lần xuất hiện của 'cũ' với :%sgn.
(Đối với ký tự đặc biệt trong 'cũ', tốt nhất tôi có thể nghĩ đến là /\V<old>. Bạn vẫn sẽ phải thoát ra \và /, tuy nhiên.)