Làm cách nào để hiển thị các dòng 2-4 sau mỗi kết quả grep?


39

Tôi đang phân tích một tệp hộp thư lưu trữ các báo cáo máy chủ email cho e-mail được gửi không thành công. Tôi muốn trích xuất các địa chỉ e-mail xấu, để tôi xóa chúng khỏi hệ thống. Tệp nhật ký trông như thế này:

...some content...
                   The mail system

<slavicatomic118@hotmail.com>: host mx1.hotmail.com[65.54.188.94] said: 550
    Requested action not taken: mailbox unavailable (in reply to RCPT TO
    command)

...some content...
                   The mail system

<oki88@optimumpro.net>: host viking.optimumpro.net[79.101.51.82] said: 550
    Unknown user (in reply to RCPT TO command)

...some content...
                   The mail system

<sigirna_luka@yahoo.com>: host mta5.am0.yahoodns.net[74.6.140.64] said: 554
    delivery error: dd This user doesn't have a yahoo.com account
    (sigirna_luka@yahoo.com) [0] - mta1172.mail.sk1.yahoo.com (in reply to end
    of DATA command)

...etc.

Địa chỉ email có 2 dòng sau một dòng với "Hệ thống thư". Sử dụng grep như thế này cho tôi dòng "Hệ thống thư" và hai dòng tiếp theo:

grep -A 2 "The mail system" mbox_file

Tuy nhiên, tôi không biết cách xóa dòng "Hệ thống thư" và dòng trống thứ hai khỏi đầu ra này. Tôi đoán rằng tôi có thể viết kịch bản PHP / Perl / Python để làm điều đó, nhưng tôi tự hỏi liệu điều này có thể với grep hoặc một số công cụ tiêu chuẩn khác. Tôi đã cố gắng đưa ra bù âm cho tham số -B:

grep -A 2 -B -2 "The mail system" mbox_file

Nhưng grep phàn nàn:

grep: -2: invalid context length argument

Có cách nào để làm điều này với grep không?


3
-B chấp nhận chữ số như -A, và nó sẽ hiển thị các dòng trước đó trước trận đấu.
Nikhil Mulley

3
Đúng, đó là sự thật, nhưng Milan không quan tâm đến những gì diễn ra trước trận đấu ... Vấn đề anh gặp phải là -A và -B chỉ chấp nhận các giá trị tích cực ... và trong mọi trường hợp, -A và -B có thể Không được sử dụng tương đối với nhau, như anh đã cố gắng làm.
Peter.O

1
Hum, chỉ để đảm bảo: đó là những địa chỉ giả mà bạn không (trực tiếp) trích xuất từ ​​tệp bạn đã cung cấp, phải không?
Matthieu M.

1
@Matthieu M. không, họ đến từ tệp nhật ký thực. Tôi hình dung vì dù sao chúng là địa chỉ không hợp lệ, điểm phát minh ra địa chỉ giả có thể hợp lệ là gì.
Milan Babuškov

Câu trả lời:


29

Cách đơn giản nhất để giải quyết nó grepchỉ bằng cách sử dụng , là đặt thêm một ống đảo ngược grepvào cuối. Ví dụ:

grep -A 4 "The mail system" temp.txt | grep -v "The mail system" | grep -v '^\d*$'

28

Nếu bạn không bị khóa khi sử dụng grep, hãy thử sed...

sed -n '/The mail system/{n;n;p}' 

Khi tìm thấy một dòng chứa "Hệ thống thư", nó sẽ đọc dòng tiếp theo hai lần, thông qua n;n;, loại bỏ từng dòng trước đó.
Điều này để lại dòng thứ 3 trong nhóm của bạn trong không gian mẫu, sau đó được in thông qua plệnh của sed .. -nTùy chọn hàng đầu ngăn tất cả các bản in khác.

Để in hai dòng tiếp theo là tốt, nó chỉ là một trường hợp tiếp theo và in n;p hai lần nữa.

sed -n '/The mail system/{n; n;p; n;p; n;p}'   

Dòng tiếp theo đọc cho các dòng bạn yêu cầu có thể được tích lũy và in một khối duy nhất chỉ với một p... Nđọc dòng tiếp theo và nối nó vào không gian mẫu,

Đây là phiên bản cô đọng cuối cùng ...

sed -n '/The mail system/{n;n;N;N;p}'   

Nếu bạn muốn một bộ tách nhóm , tương tự như đầu ra grep wouuld, bạn có thể sử dụng lệnh chèn của sed i(phải là lệnh cuối cùng trên một dòng) ...

Đây là cú pháp để bao gồm một người tách nhóm

sed -n '/The mail system/{n;n;N;N;p;i--
       }' > output-file  # or | ...

Đây là đầu ra cho trận đấu đầu tiên:

<slavicatomic118@hotmail.com>: host mx1.hotmail.com[65.54.188.94] said: 550
    Requested action not taken: mailbox unavailable (in reply to RCPT TO
    command)                                                                    
--

+1. Cảm ơn. Tôi không cần nó trong trường hợp này, nhưng tôi sẽ giữ dấu trang này trong trường hợp tôi phải xử lý những thứ phức tạp hơn.
Milan Babuškov

Đây là một câu trả lời tuyệt vời!
dotancohen

9
grep -A 2 -B -2 "The mail system" mbox_file

-B là cho các dòng trước, vì vậy không cần phải đưa ra giá trị -negative.

grep -A 2 -B 2 "The mail system" mbox_file   # This will work please check

Điều này không trả lời câu hỏi. -A 2 -B 2in từ hai dòng trước bối cảnh đến 2 dòng sau bối cảnh. Câu hỏi là về việc in từ 2 dòng sau bối cảnh thành 4 dòng sau bối cảnh.
daniel.neumann

1

Tôi thấy không có điểm nào trong việc chỉ sử dụng grep (s), trừ khi đó là một ràng buộc nghiêm ngặt. Nó không thể được thực hiện với một cuộc gọi đến grep.

grep -A 2 "The mail system" mbox_file | tail -n +3
  • grep: Tìm dòng và đầu ra 2 dòng sau,
  • đuôi: cắt 2 dòng đầu tiên (tức là bắt đầu từ dòng thứ ba).

2
Điều này chỉ hoạt động nếu có một dòng phù hợp duy nhất, có lẽ không phải là những gì câu hỏi đang hỏi.
jw013

Đó không phải là những gì câu hỏi yêu cầu nhưng nó giúp tôi trong tình huống hiện tại của tôi :-).
daniel.neumann

1
@ daniel.neumann Tôi biết, nhưng tôi chính xác đang ở trong đôi giày của bạn và nghĩ rằng Google-fu của người khác cũng sẽ dẫn đến đây.
TWiStErRob

0

Điều này in 1 dòng tiếp theo sau trận đấu regrec, sử dụng Perl

perl -ne 'print if( (/The mail system/ && ($end=1))..!$end-- )' 
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.