Tìm và thay thế bằng các biểu thức thông thường


26

Tôi có một tệp với một loạt các mặc định của người dùng. Tôi muốn thay đổi một số văn bản, nhưng tôi đang vật lộn để tìm ra một công cụ đối sánh và thay thế. Sử dụng ví dụ sau:

###############################################################################
# Trackpad, mouse, keyboard, Bluetooth accessories, and input                 #
###############################################################################

# Trackpad: enable tap to click for this user and for the login screen
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true

Tôi muốn thay thế # Trackpad: ...bằngrunning "Trackpad: ..."

Phá vỡ vấn đề, tôi đã nghĩ ra một cái gì đó bằng cách sử dụng trình kiểm tra regex:

/\n\n#\s(.*)/g

Nếu tôi thử và sử dụng cái này trong Vim thì nó không hoạt động với tôi:

:/\n\n#\s(.*)/running "\1"/g

Tôi đoán vấn đề của tôi rút ra hai câu hỏi cụ thể:

  1. Làm cách nào tôi có thể tránh tìm kiếm các \nký tự và thay vào đó hãy đảm bảo #không xuất hiện ở cuối nhóm tìm kiếm?
  2. Làm thế nào tôi có thể sử dụng hiệu quả các nhóm chụp?

Có một số câu trả lời tuyệt vời dưới đây. Khó chọn giữa cả ba, tuy nhiên tôi cảm thấy câu trả lời được chọn là chính xác nhất cho thông số ban đầu của tôi. Tôi khuyên bạn nên thử cả ba câu trả lời với tệp thực tế để xem bạn cảm thấy thế nào về chúng.

Câu trả lời:


18

Chỉ cần rõ ràng là tôi tin rằng bạn yêu cầu điều này là kết quả của sự thay thế?

###############################################################################
# Trackpad, mouse, keyboard, Bluetooth accessories, and input                 #
###############################################################################

running "Trackpad: enable tap to click for this user and for the login screen"
defaults write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true

Trong trường hợp đó, tôi khuyên dùng lệnh sau:

:%s/\n\n#\s\+\(.*\)/^M^Mrunning "\1"/

Giải thích về mẫu

:s/PATTERN/REPLACEMENT/là lệnh thay thế . Phần trăm đăng nhập :%slàm cho nó hoạt động trên toàn bộ tệp, thay vì chỉ dòng hiện tại.

Việc \n\nnói rằng dòng quan tâm phải xảy ra sau một dòng trống. Nếu bạn không quan tâm đến dòng trống trước đó, thì ^sẽ đủ.

#\s\+khớp với một ký tự băm theo sau bởi một hoặc nhiều ký tự khoảng trắng. \(.*\)chụp tất cả các văn bản tiếp theo trên dòng.

Giải thích về văn bản thay thế

^M^Mchèn hai đầu của dòng để thay thế \n\ncái đã có trong mẫu. Nếu không, văn bản sẽ được di chuyển đến cuối dòng trước dòng trống. Để gõ từng cái ^M, nhấn Ctrl-V Ctrl-M.

Sau đó, chèn chuỗi running, theo sau là bất cứ điều gì đã được ghi lại trong ngoặc đơn trong dấu ngoặc kép.


Tôi không thể chỉnh sửa câu trả lời của bạn nhưng tôi tin rằng bạn có ý nghĩa :%s/\v\n\n#\s+(.*)/^M^Mrunning "\1"/(đã thêm cờ "ma thuật"). Thật sự rất khó để chọn một câu trả lời chính xác cho câu hỏi ban đầu của tôi, nhưng tôi cảm thấy câu trả lời này là gần nhất với câu trả lời dự kiến ​​ban đầu của tôi. Nó cũng là người duy nhất hoạt động trong toàn bộ tập tin mà không cần chọn phạm vi.
Squarefrog

1
IIRC bạn có thể sử dụng \rthay vì ^Mđể có được dòng mới?
muru

11

Tôi sẽ sử dụng một cái gì đó như:

:s/^#\s\+\(.\{-}\):/running "\1":/
  • ^#để khớp với #ký tự được neo ở đầu dòng (câu trả lời này câu hỏi 1)
  • \s\+ để phù hợp với bất kỳ khoảng trắng một hoặc nhiều lần
  • \( để bắt đầu một nhóm (câu trả lời này câu hỏi 2)
  • .\{-}\để phù hợp với bất kỳ nhân vật 0 hoặc nhiều lần theo cách không tham lam ; điều này khác biệt .*ở chỗ nó cố gắng khớp ít nhất có thể, và không nhiều nhất có thể. Hãy thử thêm một :nhân vật trong bình luận để xem tại sao điều này lại quan trọng
  • \) để kết thúc nhóm con.
  • : phù hợp với một nghĩa đen :

Sau đó, chúng tôi thay thế văn bản này bằng văn bản bạn muốn và sử dụng \1để chỉ nhóm chúng tôi đã chụp.

Tôi đã nghĩ ra một cái gì đó bằng cách sử dụng một thử nghiệm regex

Cú pháp biểu thức chính quy hơi giống cú pháp wiki: có một loạt chúng, tất cả chúng trông giống nhau trong nháy mắt, không có cái nào rõ ràng tốt hơn bất kỳ cái nào khác, nhưng có nhiều điểm khác biệt.

Ngày nay, các biểu thức thông thường được gọi là "Tương thích Perl" là mặc định thực tế trong hầu hết các ngôn ngữ, nhưng các biểu thức chính quy Vim không tương thích với các biểu thức tương thích Perl! Cú pháp regrec của Vim quay trở lại ít nhất là những năm 70, khi Perl thậm chí không có mặt.

Bạn có thể thấy điều này với các nhóm con, nơi bạn phải sử dụng \(và không ((điều này tương thích với cú pháp 'cơ bản' của POSIX, nhưng không phải với cú pháp 'mở rộng' hoặc cú pháp Perl phổ biến hơn). Bạn có thể kiểm soát điều này bằng cách thêm \vcờ vào một mẫu (Xem :help /\vđể biết chi tiết), điều này sẽ làm cho nó "tương thích hơn", nhưng không hoàn toàn (Bạn vẫn phải sử dụng .{-}cho các kết quả không tham lam chẳng hạn)

Vì vậy, điều này có thể giải thích tại sao sử dụng "trình kiểm tra regex" gần như, nhưng không hoàn toàn, hoạt động.

http://www.vimregex.com/ như một tổng quan tốt / áo choàng của biểu thức chính tả Vim.


1
Câu trả lời tuyệt vời, đặc biệt là tại sao regex! = Regex. Đối với tìm kiếm và thay thế của bạn, đó là một chút khó khăn vì nhận xét có thể có hoặc không có :. Xem tập tin đầy đủ để biết chi tiết github.com/sapesfrog/dotfiles/blob/master/osx/
Kẻ

8

Bạn có thể:

  • tìm kiếm các dòng không kết thúc bằng #::/[^#]$/
  • thay thế #\s(.*)ở đầu dòng:s/\v^#\s(.*)/running "\1"/

Để sử dụng các nhóm, bạn cần phải:

  • thoát dấu ngoặc để chúng trở thành một phần của cú pháp regex: \(.*\)hoặc
  • sử dụng "ma thuật" bằng cách bắt đầu biểu thức với \v:s/\v...

Kết hợp nó:

:/[^#]$/s/\v^#\s(.*)/running "\1"/

1
Điều này hoạt động rất tốt, cảm ơn vì đã bao gồm một lời giải thích về ý nghĩa của các thẻ thay vì chỉ văn bản tôi cần viết.
Squarefrog

Cảm ơn đã làm rõ rằng các dấu ngoặc phải được thoát để trở thành một phần của cú pháp regex. Tôi luôn gặp vấn đề với các nhóm regex trong việc khiến họ làm việc.
Adama
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.