Como exibir linhas 2-4 após cada resultado do grep?

37

Estou analisando um arquivo de caixa de correio que armazena relatórios de servidor de email para emails entregues sem êxito. Desejo extrair endereços de e-mail inválidos, para que eu os remova do sistema. O arquivo de log é assim:

...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.

O endereço de e-mail vem 2 linhas depois de uma linha com "O sistema de e-mail". Usar o grep assim me fornece a linha "O sistema de mensagens" e as próximas duas linhas:

grep -A 2 "The mail system" mbox_file

No entanto, não sei como remover a linha "The mail system" e a segunda linha vazia dessa saída. Eu acho que eu poderia escrever script PHP / Perl / Python para fazer isso, mas eu me pergunto se isso é possível com o grep ou alguma outra ferramenta padrão. Eu tentei dar offset negativo para o parâmetro -B:

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

Mas o grep reclama:

grep: -2: invalid context length argument

Existe uma maneira de fazer isso com o grep?

    
por Milan Babuškov 13.02.2012 / 11:46

5 respostas

27

A maneira mais simples de resolvê-lo usando grep apenas é canalizar mais um grep invertido no final. Por exemplo:

grep -A 4 "The mail system" temp.txt | grep -v "The mail system" | grep -v '^\d*$'
    
por 13.02.2012 / 11:55
28

Se você não estiver bloqueado para usar grep , tente sed ...

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

Quando encontrar uma linha contendo "O sistema de correio", ele lerá a próxima linha duas vezes, por meio do n;n; , descartando cada linha anterior da mesma forma. Isso deixa a terceira linha do grupo no espaço padrão, que é então impressa através do comando p do sed. A opção -n principal impede todas as outras impressões.

Para imprimir as próximas duas linhas também, é apenas um caso de próximo e imprimir n;p mais duas vezes.

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

As leituras da próxima linha para as linhas que você precisa podem ser acumuladas e impressas em um único bloco com apenas um p ... N lê a próxima linha e a anexa ao espaço padrão,

Aqui está a versão condensada final ...

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

Se você quiser um grupo seperator , similar ao que o grep wouuld produz, você pode usar o comando insert do sed i (que deve ser o último comando em uma linha ) ...

Aqui está a sintaxe para incluir um separador de grupo

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

Aqui está a saída para o primeiro jogo:

<[email protected]>: host mx1.hotmail.com[65.54.188.94] said: 550
    Requested action not taken: mailbox unavailable (in reply to RCPT TO
    command)                                                                    
--
    
por 13.02.2012 / 12:51
9
grep -A 2 -B -2 "The mail system" mbox_file

-B é para linhas anteriores, portanto, não há necessidade de fornecer um valor negativo.

grep -A 2 -B 2 "The mail system" mbox_file   # This will work please check
    
por 08.11.2012 / 14:15
1

Não vejo sentido em usar apenas grep (s), exceto se for uma restrição estrita. Não pode ser feito com uma chamada para o grep.

grep -A 2 "The mail system" mbox_file | tail -n +3
  • grep: Encontre a linha e imprima duas linhas depois,
  • cauda: corte as primeiras 2 linhas (ou seja, comece na terceira linha).
por 08.11.2012 / 16:15
0

Isso imprime a próxima linha 1 após a correspondência de expressão regular, usando Perl

perl -ne 'print if( (/The mail system/ && ($end=1))..!$end-- )' 
    
por 04.09.2013 / 08:34

Tags