Yêu cầu sed bỏ qua các dòng không phù hợp


93

Làm cách nào để tạo sedbộ lọc các dòng phù hợp theo một số biểu thức, nhưng bỏ qua các dòng không khớp, thay vì để chúng in?

Như một ví dụ thực tế, tôi muốn chạy scalac(trình biên dịch Scala) trên một tập hợp các tệp và đọc từ -verboseđầu ra của nó các .classtệp đã tạo. scalac -verbosexuất ra một loạt các thông báo, nhưng chúng tôi chỉ quan tâm đến những thông báo có dạng [wrote some-class-name.class]. Những gì tôi hiện đang làm là đây ( |&là cách của bash 4.0 để chuyển hướng trình duyệt sang chương trình tiếp theo):

$ scalac -verbose some-file.scala ... |& sed 's/^\[wrote \(.*\.class\)\]$/\1/'

Thao tác này sẽ trích xuất tên tệp từ các thư mà chúng tôi quan tâm, nhưng cũng sẽ cho phép tất cả các thư khác đi qua không thay đổi! Tất nhiên thay vào đó chúng tôi có thể làm như sau:

$ scalac -verbose some-file.scala ... |& grep '^\[wrote .*\.class\]$' |
  sed 's/^\[wrote \(.*\.class\)\]$/\1/'

hoạt động nhưng trông rất giống với vấn đề thực sự, đó là cách hướng dẫn sedbỏ qua các dòng không khớp từ đầu vào. Vì vậy, làm thế nào để chúng tôi làm điều đó?


2
Câu trả lời được chấp nhận phải là câu trả lời của mouviciel: stackoverflow.com/a/1665574/869951
Oliver

Câu trả lời:


90

Một cách khác với sed đơn giản:

sed -e 's/.../.../;t;d'

s///là một nhóm thế, tkhông có bất kỳ nhãn nào có điều kiện bỏ qua tất cả các lệnh sau, dxóa dòng.

Không cần perl hoặc grep.

(được chỉnh sửa sau gợi ý của Nicholas Riley)


3
Trên OS X 10.8.2 Tôi đã phải tách txdvới một dòng mới chứ không phải là một dấu chấm phẩy như tôi đã nhận được undefined label 'x;d;:x'.
davidchambers 27/12/12

6
Thậm chí tốt hơn: sed -e 's/.../.../' -e 'tx' -e 'd' -e ':x'(được đề xuất trong một bình luận về một câu hỏi tương tự ).
davidchambers 27/12/12

1
't' sẽ chuyển đến cuối của kịch bản nếu không có nhãn được cung cấp, vì vậy đơn giản hơn: sed -e 's/.../.../' -e 't' -e 'd'.
Nicholas Riley

Mọi người không biết ý nghĩa của -equyền chọn nên không đề cập chung về nó.
Fredrick Gauss

246

Nếu bạn không muốn in các dòng không khớp, bạn có thể sử dụng kết hợp

  • -n tùy chọn thông báo cho sed không in
  • p cờ cho sed in những gì phù hợp

Điều này mang lại:

sed -n 's/.../.../p'

3
Một nhược điểm của phương pháp này là nếu bạn có nhiều biểu thức trùng khớp, kết quả cũng sẽ được in nhiều lần. Ví dụ: echo foo | sed -n -e 's/foo/bar/p' -e 's/bar/oof/p'sẽ xuất cả hai barooftrên các dòng riêng biệt. Mặc dù đa dạng nhãn goto cũng không thể xử lý nhiều mẫu vì nó sẽ xóa dòng nếu mẫu đầu tiên không khớp.
Rapsey

@Rapsey đó là bởi vì bạn đang yêu cầu nó in hai lần. Trong lệnh sed duy nhất bạn đã yêu cầu nó in hai lần, mỗi phiên bản được in tại chỗ (hoặc có thể được đệm). Bạn sẽ phải viết dấu gạch ngang thay vì -e hoặc chỉ đặt 'p' vào cuối cùng -e.
vi sinh

@Rapsey: xem câu trả lời của tôi về điểm liên quan này
Amessihel

@microiotic, nó sẽ không hoạt động vì cờ p cuối cùng sẽ hoạt động trên mỗi dòng phù hợp bởi biểu thức thay thế cuối cùng.
Amessihel

1

Sử dụng Perl:

... |& perl -ne 'print "$1\n" if /^\[wrote (.*\.class)\]$/'

0

Rapsey đã nêu ra một điểm liên quan về các biểu thức thay thế nhiều lần.

  • Đầu tiên, trích dẫn một câu trả lời Unix SE , bạn có thể "đặt trước hầu hết các lệnh sed bằng một địa chỉ để giới hạn các dòng mà chúng áp dụng".
  • Thứ hai, bạn có thể nhóm các lệnh trong dấu ngoặc nhọn {}(được phân tách bằng dấu chấm phẩy ;hoặc một dòng mới)
  • Thứ ba, thêm cờ in p vào lần thay thế cuối cùng

Cú pháp:

sed -n -e '/^given_regexp/ {s/regexp1/replacement1/flags1;[...];s/regexp1/replacement1/flagsnp}'

Ví dụ (xem tài liệu Tại đây để biết thêm chi tiết):

  • Mã:

    sed -n -e '/^ha/ {s/h/k/gp;s/a/e/g}' <<SAMPLE
    haha
    hihi
    SAMPLE
    
  • Kết quả:

    kaka
    

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.