Digamos que tengo un archivo:
# file: 'test.txt'
foobar bash 1
bash
foobar happy
foobar
Sólo quiero saber qué palabras aparecen después de "foobar", por lo que puedo utilizar este regex:
"foobar \(\w\+\)"
Los paréntesis indican que tengo un interés especial en la palabra justo después de foobar. Pero cuando hago un grep "foobar \\ ~(\w\+\)" test.txt
, obtengo las líneas enteras que coinciden con la regex completa, en lugar de sólo "la palabra después de foobar":
foobar bash 1
foobar happy
Yo preferiría que la salida de ese comando se viera así:
bash
happy
¿Existe una forma de decirle a grep que sólo muestre los elementos que coinciden con la agrupación (o una agrupación específica) en una expresión regular?
GNU grep tiene la opción -P
para regexes de estilo perl, y la opción -o
para imprimir sólo lo que coincide con el patrón. Estas opciones pueden combinarse usando aserciones de búsqueda (descritas en Patrones Extendidos en la página de manual de perlre) para eliminar parte del patrón grep de lo que se determina que ha coincidido para los propósitos de -o
.
$ grep -oP 'foobar \K\w+' test.txt
bash
happy
$
El \K
es la forma corta (y más eficiente) de (?<=patrón)
que se utiliza como una aserción de ancho cero antes del texto que se desea imprimir. (?=patrón)` puede usarse como una aserción de ancho cero después del texto que se quiere mostrar.
Por ejemplo, si quiere que coincida la palabra entre foo
y bar
, podría utilizar:
$ grep -oP 'foo \K\w+(?= bar)' test.txt
o (por simetría)
$ grep -oP '(?<=foo )\w+(?= bar)' test.txt
El grep estándar no puede hacer esto, pero las versiones recientes de GNU grep sí. Puede recurrir a sed, awk o perl. Aquí hay algunos ejemplos que hacen lo que usted quiere en su entrada de ejemplo; se comportan de manera ligeramente diferente en los casos de esquina.
Reemplazar foobar word other stuff
por word
, imprimir sólo si se hace un reemplazo.
sed -n -e 's/^foobar \([[:alnum:]]\+\).*/\1/p'
Si la primera palabra es foobar
, imprime la segunda palabra.
awk '$1 == "foobar" {print $2}'
Elimina foobar
si es la primera palabra, y salta la línea en caso contrario; entonces elimina todo lo que hay después del primer espacio en blanco e imprime.
perl -lne 's/^foobar\s+// or next; s/\s.*//; print'