Estou analisando um arquivo de caixa de correio que armazena relatórios do servidor de e-mail para e-mails entregues sem sucesso. Desejo extrair endereços de e-mail inválidos, então para removê-los do sistema. O arquivo de registro se parece com isto:

...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 após uma linha com “O sistema de correio” . Usar grep dessa forma me dá a linha “O sistema de e-mail” e as próximas duas linhas:

grep -A 2 "The mail system" mbox_file 

No entanto, eu não sei como remover o Linha “The mail system” e a segunda linha vazia desta saída. Acho que poderia escrever um script PHP / Perl / Python para fazer isso, mas me pergunto se isso é possível com grep ou alguma outra ferramenta padrão. Tentei atribuir um deslocamento negativo ao parâmetro -B:

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

Mas grep reclama:

grep: -2: invalid context length argument 

Existe uma maneira de fazer isso com grep?

Comentários

  • -B aceita numeral como -A faria, e iria exibir o linhas anteriores antes da partida.
  • Sim, é verdade, mas Milan não está ' interessado no que antecede a partida. . O problema que ele encontrou é que -A e -B aceitam apenas valores positivos … e que, em qualquer caso, -A e -B não podem ' ser usados um em relação ao outro , como ele tentou fazer.
  • Hum, só para ter certeza: esses são endereços fictícios que você não extraiu (diretamente) do arquivo que recebeu, certo?
  • @Matthieu M. não, eles são de um arquivo de log real. Percebi que, já que são endereços inválidos de qualquer maneira, qual ' é o ponto de inventar endereços fictícios que podem ser válidos.
  • stackoverflow.com/questions/8101701/…

Resposta

A maneira mais simples de resolver usando apenas grep é 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*$" 

Resposta

Se você não estiver preso a usando grep, tente sed

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

Quando encontra uma linha contendo “O sistema de correio”, lê a próxima linha duas vezes, através do n;n;, descartando cada linha anterior ao fazê-lo.
Isso deixa a terceira linha do seu grupo no espaço do padrão, que é então impresso pelo comando sed “s p. A opção -n principal impede todas as outras impressões .

Para imprimir as próximas duas linhas também, é apenas o 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 pN lê a próxima linha e a anexa ao espaço do padrão,

Aqui está a versão condensada final …

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

Se você quiser um separador de grupo , semelhante ao que grep produziria, você pode usar o comando sed “s insert 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á o resultado da primeira correspondência:

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

Comentários

  • +1. Obrigado. Eu não ' não preciso disso neste caso, mas eu ' vou manter isso marcado para o caso de eu conseguir coisas mais complicadas para lidar.
  • Esta é uma ótima resposta!

Resposta

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

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

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

Comentários

  • Isso não responde à pergunta. -A 2 -B 2 imprime de duas linhas antes do contexto a 2 linhas depois do contexto. A questão é sobre a impressão de 2 linhas após o contexto para 4 linhas após o contexto.

Resposta

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

grep -A 2 "The mail system" mbox_file | tail -n +3 
  • grep: Encontre a linha e produza 2 linhas depois,
  • tail: corte as 2 primeiras linhas (ou seja, comece na terceira linha).

Comentários

  • Isso só funciona se houver uma única linha correspondente, o que provavelmente não é o que a pergunta está perguntando.
  • Isso não é nada que a pergunta pediu, mas me ajuda na minha situação atual :-).
  • @ daniel.neumann Eu sei, mas estava exatamente no seu lugar e pensei que os outros ' Google-fu vão liderar aqui também.

Resposta

Se quiser remover as primeiras 2 linhas, canalize para sed

sed "1,2d" 

como em

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

Comentários

  • Você não percebeu que o padrão ocorre muitas vezes. Se “O sistema de correio” aparecer nas linhas 4, 14, 24, 34, …, o OP deseja ver as linhas 6, 16, 26, 36, … Sua resposta dará 6, 14-16, 24-26, 34- 36,….

Resposta

Isso imprime a próxima linha 1 após a correspondência regexp, usando Perl

perl -ne "print if( (/The mail system/ && ($end=1))..!$end-- )" 

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *