Làm cách nào để thay thế nhiều dòng bằng một từ trong tệp (thay thế tại chỗ)?


9

Nội dung filenametệp của tôi như sau (ví dụ):

My block of line starts from here 
START
First line
second line
third line
END
and end to here for example.

Tôi muốn thay thế khối dòng giữa STARTENDchỉ bằng một từ duy nhất, ví dụ như với SINGLEWORD. Giống như dưới đây:

My block of line starts from here 
SINGLEWORD
and end to here for example.

Tôi có thể tìm thấy khối dòng của mình bằng cách sử dụng lệnh này:

grep -Pzo "START(.|\n)*END" filename

Và kết quả của việc chạy lệnh trên sẽ như thế này:

START
First line
second line
third line
END

Sau đó, tôi đã sử dụng lệnh này để kết hợp tất cả các dòng thành một dòng duy nhất:

LAST_RESULT | sed -e :a -e '/$/N; s/\n/ /; ta'

Sau đó tôi sẽ nhận được kết quả này:

START First line second line third line END

Và với lệnh cuối cùng của tôi, LAST_RESULTS | sed 's/.*/SINGLEWORD/'tôi thay đổi chúng "SINGLEWORD"và tôi nhận được kết quả này.

SINGLEWORD

Bây giờ điều tôi muốn là: Làm thế nào tôi có thể sử dụng lệnh này (Hoặc lệnh gợi ý của bạn) và thay thế (tại chỗ) khối dòng của tôi thành từ "SINGLEWORD"? Và kết quả cuối cùng sẽ giống như tập tin này:

My block of line starts from here 
SINGLEWORD
and end to here for example.

Câu trả lời:


14

Điều này có thể được thực hiện rất dễ dàng trong perl:

$ perl -i -p0e 's/START.*?END/SINGLEWORD/s' file
$ cat file
My block of line starts from here 
SINGLEWORD
and end to here for example. 

Giải trình

-0 đặt dấu phân cách thành null

-páp dụng tập lệnh được cung cấp bởi -emỗi dòng và in dòng đó

Công cụ sửa đổi regrec:

  • /sCoi chuỗi là dòng đơn. Đó là, thay đổi .để phù hợp với bất kỳ nhân vật nào, ngay cả một dòng mới, thông thường nó sẽ không phù hợp.

Tại sao ?:

  • Theo mặc định, một mô hình con được định lượng là "tham lam", nghĩa là nó sẽ khớp nhiều lần nhất có thể (với một vị trí bắt đầu cụ thể) trong khi vẫn cho phép phần còn lại của mẫu khớp với nhau. Nếu bạn muốn nó khớp với số lần tối thiểu có thể, hãy làm theo bộ định lượng với a ?.

@KasiyA: Sử dụng sednên có thể nhưng có lẽ khó đọc hơn (Xem câu hỏi này )
Sylvain Pineau

Một hơn vì START và END mô hình của tôi có ký tự đặc biệt ( /, *, ?) trong đó và đây chỉ là ví dụ. và bạn có thể giải thích lệnh của bạn.
αғsнιη

@KasiyA bạn có thể thoát khỏi nhân vật như vậy với \ (chính xác như với sed): \/, \*,\?
Sylvain Pineau

@KasiyA Mình đã thử perl -i -p0e 's/\/\*.*?\*\//SINGLEWORD/sm'. Nó sẽ hoạt động
Sylvain Pineau

@KasiyA Tôi nghĩ rằng tôi đã hoàn thành việc giải thích ngay bây giờ;)
Sylvain Pineau

14

Tôi đã tự hỏi nếu điều này là có thể mà không có perl, pythonvà những người khác. Và tôi tìm thấy giải pháp này bằng cách sử dụng sed:

$ sed ':a;N;$!ba;s/START.*END/SINGLEWORD/g' filename

Giải trình:

  1. : a tạo nhãn 'a'
  2. N nối dòng tiếp theo vào không gian mẫu
  3. $! nếu không phải là dòng cuối cùng , ba nhánh (đi đến) nhãn 'a'
  4. s thay thế , /START.*END/bởi SINGLEWORD, / g trận đấu toàn cầu (nhiều lần có thể)

Nó đã được tìm thấy ở đây .

@KasiyA, cảm ơn bạn tôi đã học được rất nhiều điều thú vị!

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.