Estou analisando um arquivo de caixa de correio que armazena relatórios do servidor de email para emails entregues sem êxito. Desejo extrair endereços de email incorretos, para removê-los do sistema. O arquivo de log fica 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 após uma linha com "O sistema de e-mail". Usar grep como este me dá a linha "O sistema de correio" e as próximas duas linhas:
grep -A 2 "The mail system" mbox_file
No entanto, não sei como remover a linha "O sistema de email" e a segunda linha vazia desta saída. Eu acho que eu poderia escrever script PHP / Perl / Python para fazer isso, mas gostaria de saber se isso é possível com grep ou alguma outra ferramenta padrão. Eu tentei dar deslocamento 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?
Respostas:
A maneira mais simples de resolvê-lo usando
grep
apenas é canalizar mais um invertidogrep
no final. Por exemplo:fonte
Se você não está preso ao uso
grep
, tentesed
...Quando encontra uma linha contendo "O sistema de correio", lê a próxima linha duas vezes, via
n;n;
, descartando cada linha anterior ao fazê-lo.Isso deixa a terceira linha do seu grupo no espaço do padrão, que é impresso através do
p
comando sed . A-n
opção principal impede todas as outras impressões.Para imprimir as próximas duas linhas também, é apenas um caso da próxima e imprima
n;p
duas vezes mais.As leituras da próxima linha das linhas necessárias podem ser acumuladas e impressas em um único bloco com apenas uma
p
...N
lê a próxima linha e a anexa ao espaço do padrão,Aqui está a versão condensada final ...
Se você quiser um separador de grupo , semelhante ao que o grep deseja, você pode usar o comando insert do sed
i
(que deve ser o último comando de uma linha) ...Aqui está a sintaxe para incluir um separador de grupo
Aqui está a saída para a primeira correspondência:
fonte
-B
é para linhas anteriores, portanto, não há necessidade de fornecer um valor negativo.fonte
-A 2 -B 2
imprime de duas linhas antes do contexto para 2 linhas após o contexto. A questão é sobre a impressão de 2 linhas após o contexto e 4 linhas após o contexto.Não vejo sentido em usar apenas grep (s), exceto se for uma restrição estrita. Isso não pode ser feito com uma chamada para grep.
fonte
Isso imprime a próxima 1 linha após a correspondência regexp, usando Perl
fonte