Có thể khớp nhiều số dòng cụ thể (không phải phạm vi) với sed không?


9

Xem xét:

echo -e "a\nb\nc\nd\ne\nf\ng\nh" | sed '3,5a test'

Điều này sẽ phù hợp với dòng 3, 4 và 5.

Nhưng tôi đang cố gắng chỉ khớp dòng 3 và 5 (không phải 4). Và nối 'kiểm tra' sau chúng.

Câu trả lời:


9
echo ... | sed -e '3a test' -e '5a test'

Nếu thao tác phức tạp hơn trong trường hợp này thì bạn có thể sử dụng cấu trúc như thế này:

sed 'b pattern; : action; a \
lalala
b end; : pattern; 3b action; 5b action; : end'

Tức là bạn đặt tất cả các lệnh bạn cần giữa b pattern;b end;.

Và bạn thêm tất cả các mẫu của bạn (số dòng hoặc bất cứ điều gì) sau : pattern;.

Điều gì xảy ra là thế này:

  1. Lệnh đầu tiên nhảy qua phần hành động (có thể dễ đọc hơn nếu các mẫu ở đầu và b end;trực tiếp trước phần hành động).

  2. Nếu một mẫu phù hợp thì thực thi nhảy đến phần hành động. Sau khi thực hiện phần hành động nhảy đến cuối.

Tôi cố gắng dọn dẹp cái này:

sed '3b action; 5b action; b end; : action; a \
lalala
: end'

Trong một dòng duy nhất sẽ như sau:

sed "3b idAction; 5b idAction; b; : idAction; a test"

Có thể, bạn cần phải viết nó:

sed '
   3b action
   5b action
   b
   : action
   a\
   lalala'

( bkhông có các nhánh nhãn đến cuối, vì vậy bạn không cần một endnhãn rõ ràng , ;là một ký tự trong nhãn trong các sedtriển khai tiêu chuẩn ).


4
Wow, chương trình con sed.
Thật

Wow thực sự, bạn có thể mở rộng trên những? Chúng trông thực sự hữu ích!
terdon

một mô hình với 'mẫu' và 'hành động' có vẻ rất tốt vì tôi không cần lặp lại 'thử nghiệm' (hoặc 'lalala'), vẫn phải hiểu rõ hơn về nó! :)
Sức mạnh Bảo Bình

@terdon Tôi có thể làm gì?
Hauke ​​Laging

Tôi có nghĩa là cái thứ hai trông tuyệt vời nhưng khó hiểu và nếu bạn có thời gian, tôi đánh giá cao một lời giải thích.
terdon

5

Với sed(xem câu trả lời của @ HaukeLaging )

Với awk:

$ echo -e "a\nb\nc\nd\ne\nf\ng\nh" | awk 'NR==3 || NR==5{$0=$0"\ntest"}1;'

Với perl:

$ echo -e "a\nb\nc\nd\ne\nf\ng\nh" | perl -pe '$_ .="test\n" if $. == 3 || $. == 5'

Có thể đánh golf perl của bạn một chút, bằng cách sử dụng toán tử "kết hợp thông minh":perl -lnE 'say if $. ~~ @{[3,5]}'
glenn jackman

@glennjackman ah, đúng vậy, cảm ơn. Tôi phải thừa nhận rằng tôi có một chút cảnh giác ~~, không hiểu nó cũng như tôi nên làm. Ngoài ra, cả say~~cần perl v> = 5.10 phải không?
terdon

Tôi cần phải thêm 'kiểm tra' sau những dòng đó, tôi thấy bây giờ sẽ tốt hơn nếu làm rõ điều đó ngay từ đầu. Tôi vừa chỉnh sửa OP.
Sức mạnh Bảo Bình

@AquariusPower, perl -pE 'say "test" if $. ~~ @{[4,6]}'- đây prepends dòng: perl của -phiện một in ngầm tại cuối của chương trình nhất định.
glenn jackman

@AquariusPower cũng thấy câu trả lời cập nhật.
terdon

3

Như @HaukeLaging aleady đã nói, lệnh này thực hiện những gì bạn muốn:

sed -e'3a test' -e'5a test'

Bây giờ, điều này có thể trở nên khá cồng kềnh để gõ nếu bạn muốn khớp, ví dụ: 20 dòng.

Trong những trường hợp này, giả sử shell của bạn hỗ trợ mở rộng dấu ngoặc , bạn có thể sử dụng lệnh này thay thế:

sed -e{3,5}'a test'

(Lưu ý rằng dấu ngoặc nhọn và dấu phẩy phải không được trích dẫn.)

Kết quả là, shell sẽ truyền các đối số tới -e3a test-e5a testsed, đó chính xác là những gì lệnh đầu tiên làm.

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.