Estoy analizando un archivo de buzón que almacena informes del servidor de correo electrónico para el correo electrónico entregado sin éxito. Deseo extraer direcciones de correo electrónico incorrectas, de modo que las elimine del sistema. El archivo de registro se ve así:
...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.
La dirección de correo electrónico viene 2 líneas después de una línea con "El sistema de correo". Usar grep de esta manera me da la línea "El sistema de correo" y las siguientes dos líneas:
grep -A 2 "The mail system" mbox_file
Sin embargo, no sé cómo eliminar la línea "El sistema de correo" y la segunda línea vacía de esta salida. Creo que podría escribir un script PHP / Perl / Python para hacerlo, pero me pregunto si esto es posible con grep o alguna otra herramienta estándar. Traté de dar un desplazamiento negativo al parámetro -B:
grep -A 2 -B -2 "The mail system" mbox_file
Pero grep se queja:
grep: -2: invalid context length argument
¿Hay alguna manera de hacer esto con grep?
Respuestas:
La forma más sencilla de resolverlo usando
grep
solo es canalizar uno más invertidogrep
al final. Por ejemplo:fuente
Si no está bloqueado para usar
grep
, intentesed
...Cuando encuentra una línea que contiene "El sistema de correo", lee la siguiente línea dos veces, a través de
n;n;
, descartando cada línea anterior al hacerlo.Esto deja la tercera línea de su grupo en el espacio del patrón, que luego se imprime mediante el
p
comando de sed . La-n
opción principal evita todas las demás impresiones.Para imprimir también las siguientes dos líneas, es solo un caso de siguiente e imprime
n;p
dos veces más.Las lecturas de la siguiente línea para las líneas que necesita se pueden acumular e imprimir en un solo bloque con solo una
p
...N
lee la siguiente línea y la agrega al espacio del patrón,Aquí está la versión condensada final ...
Si desea un separador de grupo , similar a la salida de grep wouuld, puede usar el comando de inserción de sed
i
(que debe ser el último comando en una línea) ...Aquí está la sintaxis para incluir un separador de grupo
Aquí está la salida para el primer partido:
fuente
-B
es para líneas anteriores, por lo que no es necesario dar un valor negativo.fuente
-A 2 -B 2
imprime desde dos líneas antes del contexto hasta 2 líneas después del contexto. La pregunta se trata de imprimir desde 2 líneas después del contexto hasta 4 líneas después del contexto.No veo ningún punto en usar solo grep (s), excepto si es una restricción estricta. No se puede hacer con una llamada a grep.
fuente
Esto imprime la siguiente línea 1 después de la coincidencia regexp, usando Perl
fuente