Làm thế nào để thay thế một mã nhiều dòng bằng sed?


9

Tôi có một tập tin lớn có các ký tự đặc biệt trong đó. Có một mã nhiều dòng ở đó, mà tôi muốn thay thế bằng sed.

Điều này:

  text = "\
    ------                                                           ------\n\n\
    This message was automatically generated by email software\n\
    The delivery of your message has not been affected.\n\n\
    ------                                                           ------\n\n"

Cần biến thành thế này:

text = ""

Tôi đã thử mã sau đây, nhưng không có may mắn:

sed -i '/  text = "*/ {N; s/  text = .*affected.\./  text = ""/g}' /etc/exim.conf

Nó không thay thế bất cứ điều gì và không hiển thị bất kỳ thông báo lỗi

Tôi đã chơi với nó, nhưng mọi thứ tôi thử đều không hoạt động.


Có cần phải sedhoặc bạn đang mở cho các công cụ khác? Có thể có "bên trong text=khối? Có thể có trường hợp khác text = trong tập tin của bạn? Sẽ luôn có 4 dòng văn bản hoặc có thể có nhiều hơn / ít hơn?
terdon

Tốt hơn là sed, hoặc bất cứ thứ gì không yêu cầu cài đặt trong máy chủ CentOS. Công cụ ra khỏi hộp
blade19899

@terdon Không có cái nào khác text = trong thư mục, cần phải có text = "". Các tập tin có 891 dòng mã. Vì vậy, nó cần te tôn trọng các văn bản khác.
lưỡi19899

Bạn có muốn ghi đè lên tập tin hoặc chỉ sửa đổi đầu ra?
joH1

@Moonstroke KHÔNG QUÁ TUYỆT VỜI. Nó chỉ cần thay thế văn bản - như đã thấy trong câu hỏi của tôi - đến text = "". Như đã thấy trong câu hỏi của tôi.
lưỡi19899

Câu trả lời:


15

Perl để giải cứu:

perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
  • -i~ sẽ chỉnh sửa tập tin "tại chỗ", để lại một bản sao lưu
  • -0777 đọc toàn bộ tập tin cùng một lúc, không phải từng dòng

Sự thay thế s///hoạt động tương tự như trong sed (nghĩa là nó khớp với text = "bất kỳ thứ gì ngoại trừ trích dẫn kép nhiều lần cho đến trích dẫn kép), nhưng trong trường hợp này, nó hoạt động trên toàn bộ tệp.


5

Bạn phải kiểm tra không gian mẫu và tiếp tục kéo vào Ndòng ext nếu nó không khớp, vd

sed '/text = "/{              # if line matches text = "
:b                            # label b
$!N                           # pull in the next line (if not the last one)
/"$/!bb                       # if pattern space doesn't end with " go to label b
s/".*"/""/                    # else remove everything between the quotes
}' infile

với gnu sedbạn có thể viết nó như là

sed '/text = "/{:b;$!N;/"$/!bb;s/".*"/""/}' infile

Tuy nhiên, điều đó không hiệu quả lắm, tốt hơn là chỉ chọn phạm vi /text = "/,/"/, sửa đổi dòng đầu tiên và xóa phần còn lại:

sed '/text = "/,/"/{            # in this range
/text = "/!d                    # delete all lines not matching text = "
s/\\/"/                         # replace the backslash with quotes (this is only
}' infile                       # executed if the previous d wasn't executed)

một lần nữa, với gnu sedbạn có thể viết nó dưới dạng một lớp lót:

sed '/text = "/,/"/{/text = "/!d;s/\\/"/}' infile

3

Cá nhân, tôi sẽ làm điều này trong Perl. Nếu chúng tôi có thể cho rằng không có "trước khi kết thúc ", bạn có thể làm:

perl -0pe 's/(text\s*=\s*)".*?"/$1""/s' file

Các -0tập tin toàn bộ tập tin, đọc nó vào bộ nhớ. Có -pnghĩa là "in mọi dòng (ở đây, một" dòng "sẽ là toàn bộ tệp) sau khi áp dụng tập lệnh được đưa ra bởi -e". Kịch bản lệnh là một toán tử thay thế đơn giản. Nó sẽ nắm bắt chuỗi texttheo sau bởi 0 hoặc nhiều ký tự khoảng trắng, một =và 0 hoặc nhiều khoảng trắng nữa ( text\s*=\s*) và lưu nó dưới dạng $1. Sau đó, nó sẽ thay thế mẫu đã chụp cũng như chuỗi trích dẫn ngắn nhất mà nó tìm thấy bằng mẫu ( $1) và "". Các slá cờ làm .newlines trận đấu.


sửa chữa, -00đọc trong đoạn văn, không phải toàn bộ tập tin ( ref ). Nếu văn bản trong dấu ngoặc kép chứa một dòng trống, thì biểu thức chính quy sẽ không khớp.
glenn jackman

@glennjackman argh! Tôi luôn luôn có được những hỗn hợp. . Đó là lý do tại sao tôi thực sự kiểm tra lại bằng cách thêm một đoạn thêm và chạy perl -00ne 'print;exit'. Và tôi vẫn đặt sai trong câu trả lời của tôi! Cảm ơn, đã sửa ngay.
terdon
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.