Tìm kiếm và thay thế nhiều dòng


8

Muốn thực hiện tìm kiếm và thay thế trong một tệp có 12000 dòng.

Cụ thể, nếu sự xuất hiện ^ SetFontSize 28tồn tại sau một ^Hidekhối và trước lần tiếp theo ^Hidehoặc ^Show, thay đổi 28thành 18.

Đây là một đoạn trích từ tệp gốc.

Hide # Gear - Endgame
    ItemLevel >= 77
    Rarity = Magic
    LinkedSockets >= 3
    BaseType "Runic Hatchet"
    SetTextColor 140 190 255 # Magic Item Highlight
    SetFontSize 28

Hide # Gear - Endgame
    ItemLevel >= 77
    Rarity = Magic
    Sockets >= 3
    BaseType "Runic Hatchet"
    SetTextColor 140 190 255 # Magic Item Highlight
    SetFontSize 28

Show # Gear - Endgame
    ItemLevel >= 83
    Rarity = Normal
    Sockets < 3
    BaseType "Tiger Hook"
    SetTextColor 240 240 240 # Normal Item Highlight
    SetBackgroundColor 70 70 70
    SetFontSize 28

Kết quả cuối cùng cho một trong các Hidekhối sẽ như thế này:

Hide # Gear - Endgame
    ItemLevel >= 77
    Rarity = Magic
    LinkedSockets >= 3
    BaseType "Runic Hatchet"
    SetTextColor 140 190 255 # Magic Item Highlight
    SetFontSize 18

Thay thế SetFontSize 28để SetFontSize 18, nhưng chỉ khi nó xuất hiện trong một ^Hidekhối.

Regex khó chịu tôi đã thử là: :%s/^Hide\(.*\)SetFontSize 28$/Hide\1SetFontSize 18/g

Nhưng đã nói mẫu không tìm thấy. Vui lòng cho tôi biết nếu có bất kỳ thông tin bổ sung nào được yêu cầu hoặc nếu yêu cầu của tôi không rõ ràng.


5
Có phải mọi Hidekhối đều có một SetFontSizedòng (bất cứ giá trị nào)? Nếu vậy, bạn có thể sử dụng:%s/Hide\_.\{-\}SetFontSize \zs28/18/
muru

2
@muru whatever be the valuesẽ gây rắc rối, giải pháp của bạn chỉ hoạt động nếu mỗi Hidekhối có một SetFontSizedòng và giá trị của nó là chính xác 28, nếu không, nó khớp với 28khối khác.
depowsdi

Câu trả lời:


2

Một cách để giải quyết điều này là sử dụng :globalđể tạo ra một đầu ra phạm vi.

Sử dụng globallệnh điển hình sẽ là

:[range]g/{pattern}/[cmd]

Nó cũng có tùy chọn làm cho mẫu này tạo ra một phạm vi thay vì khớp một dòng bằng cách sử dụng ,ở dạng

:[range]g/{first pattern}/,/{second pattern}/[cmd]

Điều này tạo ra một phạm vi được áp dụng cho lệnh.

Ví dụ bạn mô hình đầu tiên sẽ được phù hợp với người đầu tiên Hidenhập cảnh và mô hình thứ hai là một trong hai Hide, Showhoặc cuối của tập tin (giả sử bạn muốn điều đó Hide trường hợp cuối cùng).

:g/Hide/,/\(Hide\|Show\|\%$\)/s/SetFontSize 28/SetFontSize 18/

Regex đầu tiên là đơn giản /Hide/,. Regex thứ hai chứa một vài phần thú vị.

  • \(\)tạo ra một nhóm các nguyên tử phù hợp
  • \| là hoạt động OR
  • \%$ đại diện cho phần cuối của tập tin

Khi chúng tôi đã xác định phạm vi của mình, chúng tôi áp dụng thay thế bằng một mẫu và một chuỗi giống như bạn thường làm.

Xin lưu ý rằng regex được sử dụng trong ví dụ này là rất cơ bản. Bạn sẽ muốn đảm bảo rằng số nhận dạng của bạn cho phần đầu và phần cuối của phạm vi sẽ chụp đúng khu vực.


2

Có vẻ như regex khó chịu của bạn không đủ khó chịu ... :-)

Phần tìm kiếm

Tìm kiếm sẽ phải được thay đổi thành này:

^Hide\(\(\(Show\|Hide\)\@!\_.\)*\)SetFontSize 28

Điều này bao gồm khá nhiều điều không phổ biến và rất nhiều dấu ngoặc đơn ... Hãy xem những gì chúng ta có trong đó:

Caret ( ^)

Các dấu mũ được sử dụng để có nghĩa là bắt đầu của dòng. Tôi nghĩ rằng chúng ta đã quen thuộc với điều này.

Một điểm quan trọng, ^không hoạt động trừ khi là nhân vật đầu tiên trong mẫu của bạn. Sau khi nó được thực hiện nguyên văn. Để bao gồm một dòng bắt đầu trong biểu thức của bạn, bạn cần sử dụng \_^. Tuy nhiên, trong tình huống của chúng tôi, chúng tôi không cần điều đó.

(Có một hiện tượng tương tự với $\_$)

Dấu ngoặc đầu tiên và cuối cùng ( \( ... \))

Dấu ngoặc đầu tiên và cuối cùng được sử dụng riêng , điều đó có nghĩa là nó sẽ lấy bất cứ thứ gì xuất hiện bên trong và đặt nó trong tham số \1. Bạn đã sử dụng nó trong regex của riêng bạn, vì vậy tôi sẽ cho rằng bạn cũng quen với cái này.

Bộ dấu ngoặc đơn thứ hai

Như bạn có thể nhận thấy, có một bộ dấu ngoặc đơn thứ hai theo sau là dấu hoa thị \( ... \)*. Điều này có nghĩa là chúng tôi đang tìm kiếm bất cứ điều gì phù hợp với bất kỳ số lần. Đây là cách thông thường để sử dụng dấu hoa thị, vì vậy bạn nên làm quen với nó.

Bộ dấu ngoặc đơn thứ ba, HOẶC và \_.

Vâng, thực sự có ba dấu ngoặc đơn trước từ này Show. Bộ cuối cùng này là cần thiết vì hai lý do: \|và sau đây @!.

Liên quan đến hoạt động OR, bạn đã quen thuộc với nó.

Show\|Hide    or    Hide\|Show

Thứ tự không quan trọng ở đây. Điều \cần thiết ở phía trước |để làm việc trong vim.

Dấu ngoặc quanh biểu thức này cho phép chúng ta theo dõi biểu thức bằng một cái gì đó . Đây @!.

\(Show\|Hide\)@!

Cái này ít quen thuộc hơn nhiều. Nó có nghĩa là nếu không phù hợp . Tuy nhiên, việc sử dụng này không phải là rất dễ dàng, nhưng bạn cần tuân theo biểu thức đó với những gì bạn muốn trích xuất không phù hợp với biểu thức đã nói. Đây là lý do tại sao chúng ta có \_.đằng sau mô hình đó.

Các \_.phương tiện phù hợp với bất cứ điều gì. Trái ngược với chính .nó, không phù hợp với \nnhân vật. Nói cách khác, chúng tôi khớp bất kỳ ký tự nào trên bất kỳ số dòng nào trừ khi nó khớp Showhoặc Hide.

Lưu ý rằng dấu ngoặc đơn xung quanh biểu thức đó cũng quan trọng như dấu hoa thị, vì vậy toàn bộ điều này thực sự là điều làm cho nó hoạt động:

\(\(Show\|Hide\)@!\_.\)*

aka đối sánh số tiền lên đến tiếp theo Showhoặc Hideký tự (lưu ý rằng nó cũng sẽ phù hợp với Showing, Shower, HideMe, vv bạn sẽ có thể sử dụng \<\>nếu nó là cần thiết để phù hợp với lời chính xác.)

Lưu ý bên: để tìm kiếm trên nhiều dòng, cũng có thể sử dụng \nký tự trong mẫu. Tuy nhiên, nó không linh hoạt hơn \_.mẫu.

SetFontSize 28

Bây giờ phần phải bao gồm SetFontSize 28là tốt. Giống như bạn đã có trong regex của bạn. Nếu không SetFontSize 28xuất hiện trong phần đó, hãy thử tìm kiếm lại trong phần tiếp theo.

Do sự phủ định ở trên (trận đấu ngoại trừ Showhoặc Hide), tìm kiếm không bị rò rỉ sang phần tiếp theo, có nguy cơ làm hỏng nó.

Bộ phận thay thế

Sự thay thế giống như bạn đã có:

.../Hide\1SetFontSize 18/

Chúng tôi sử dụng dấu ngoặc đơn trong Tìm kiếm để \1công việc như mong đợi.

Hoàn thành Tìm kiếm và Thay thế

Các mô hình kết quả như thế này:

:%s/^Hide\(\(\(Show\|Hide\)@!\_.\)*\)SetFontSize 28/Hide\1SetFontSize 18/

Các \(Show\|Hide\)nên bao gồm tất cả các khả năng tiêu đề .

Nguồn

Regex để khớp với bất kỳ ký tự nào, kể cả dòng mới ( \_.\{-})

Tìm kiếm các dòng không chứa mẫu và các tìm kiếm hữu ích khác ( @!)

Tài liệu Vim: mẫu ( \_^)


1
Tôi thích ()*, phiên bản câu trả lời của bạn : %s/\v^Hide.*\n(\s+.*\n)*\s*SetFontSize\s+\zs28/16.
depowsdi
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.