2009-06-10 16 views
9

que tienen un archivo de registro que contiene una serie de líneas de error, tales como:¿Puedes grep un archivo usando una expresión regular y solo muestra la parte correspondiente de una línea?

Failed to add [email protected] to database 

que puede filtrar estas líneas con una sola llamada grep:

grep -E 'Failed to add (.*) to database' 

Esto funciona bien, pero lo que Lo que realmente me gustaría hacer es tener grep (u otro comando de Unix al que le paso la salida) solo muestra la dirección de correo electrónico de la línea correspondiente.

¿Esto es posible?

Respuesta

5

Puede usar sed:

grep -E 'Failed to add (.*) to database'| sed 's/'Failed to add \(.*\) to database'/\1' 
+4

Uso de la opción -o de grep es más simple ... – bortzmeyer

+0

-o no es suficiente, sin embargo, ¿verdad? ref: http://stackoverflow.com/a/1140415/32453 – rogerdpack

+0

@rogerdpack: Parece que tienes razón. '-o' devolvería el conjunto de cadenas 'Error al agregar *[email protected]* a la base de datos', mientras que OP solo quiere *[email protected]*. –

1

o Python:

cat file | python -c "import re, sys; print '\r\n'.join(re.findall('add (.*?) to', sys.stdin.read()))" 
15

sed es bien sin grep:

sed -n 's/Failed to add \(.*\) to database/\1/p' filename 
+0

¡Seguramente podría usar awk también! – RandomNickName42

+0

sed puede hacerlo en un solo comando ... – rogerdpack

2

Esto debería hacer el trabajo:

grep -x -e '(?<=Failed to add).+?(?= to database)' 

Utiliza una aserción positiva de búsqueda anticipada, seguida de la coincidencia de la dirección de correo electrónico, seguida de una afirmación de observación posterior. Esto asegura que coincida con toda la línea, pero solo consume (y así devuelve) la parte de la dirección de correo electrónico.

La opción -x especifica que grep debe coincidir con las líneas en lugar de con el texto completo.

-1

Si desea usar grep, sería más apropiado usar egrep;

About egrep 

Search a file for a pattern using full regular expressions. 

grep no siempre tendrá la funcionalidad completa para regex.

+1

Él ya usa egrep ya que usa -E. NO tiene nada que ver con el problema que es controlar la salida. – bortzmeyer

+0

¿De qué estás hablando?Si ve la "etiqueta", pregunta por * UNIX * grep, que no es (como sugiere su respuesta) GNU-Everywhere, consulte http://www.softpanorama.org/Tools/Grep/grep_reference.shtml para algunos revisión de las diversas versiones de grep en UNIX (NO GNU GREP), lo que verá en blanco y negro, "Regex limitado - grep", "Regex extendido - egrep". Así _REGARDLESS_ del hecho de que GNU grep puede ser (es) mejor, no va a ser algo con lo que * siempre * puedas contar, desplegado y disponible para todos tus scripts. Mi punto es que no puedes contar con grep "basic" – RandomNickName42

+0

No veo el punto. El OP no dijo nada sobre el sistema operativo que usa, excepto "Unix". Entonces puede ser un Unix donde GNU grep es el predeterminado (Debian, por ejemplo) o un Unix donde GNU grep podría instalarse inmediatamente con un comando (NetBSD con pkg_add textproc/grep) – bortzmeyer

2

Las versiones recientes de GNU grep tienen una opción -o que hace exactamente lo que usted desea. (-o es para --only-matching).

+4

usando '-o' mostraría la parte correspondiente regex inssted de toda la línea en la que se encontró el partido. pero @Olly solo quería el primer subgrupo (la dirección de correo electrónico, sin el texto que lo rodea). –

3

Usted también puede simplemente tubería grep para sí mismo :)

grep -E 'Failed to add (.*) to database' | grep -Eo "[^ ][email protected][^ ]+" 

O, si las "líneas" de interés son los únicos con mensajes de correo electrónico, sólo tiene que utilizar el último comando grep sin la primera.

-1

-r opción para sed permite expresiones regulares sin barras invertidas

sed -n -r 's/Failed to add (.*) to database/\1/p' filename 
Cuestiones relacionadas