如何在每个 grep 结果后显示第 2-4 行?

如何在每个 grep 结果后显示第 2-4 行?

我正在解析一个邮箱文件,该文件存储未成功发送的电子邮件的电子邮件服务器报告。我希望提取不良电子邮件地址,以便将它们从系统中删除。日志文件如下所示:

...some content...
                   The mail system

<[email protected]>: 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

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

...some content...
                   The mail system

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

...etc.

电子邮件地址位于“邮件系统”一行之后的两行。像这样使用 grep 给我“邮件系统”行和接下来的两行:

grep -A 2 "The mail system" mbox_file

但是,我不知道如何从此输出中删除“邮件系统”行和第二个空行。我想我可以编写 PHP/Perl/Python 脚本来做到这一点,但我想知道这是否可以使用 grep 或其他一些标准工具实现。我尝试给 -B 参数提供负偏移量:

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

但 grep 抱怨道:

grep: -2: invalid context length argument

有没有办法用 grep 来做到这一点?

答案1

解决这个问题的最简单方法grepgrep在最后再倒一个管道。例如:

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

答案2

如果您没有被锁定使用grep,请尝试sed...

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

当它找到包含“邮件系统”的行时,它会通过 读取下一行两次,n;n;同时丢弃前面的每一行。
这会将您的组的第三行留在模式空间中,然后通过 sed 打印p命令打印该行。前导-n选项阻止所有其他打印。

要打印接下来的两行,这只是一个例子下一步并打印 n;p又两次。

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

您需要的行的下一行读取可以累积并打印在一个块中,只需一个p... N读取下一行并将其附加到模式空间,

这是最终的精简版本......

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

如果你想要一个组分隔符,类似于 grep 输出的内容,您可以使用 sed 的插入命令i(必须是一行中的最后一个命令)...

这是包含一个的语法组分隔符

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

这是第一场比赛的输出:

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

答案3

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

-B用于前面的行,因此不需要给出负值。

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

答案4

如果你想删除前两行,请将其通过管道传输到sed

sed '1,2d'

grep -A 2 "The mail system" mbox_file | sed '1,2d'

相关内容