¿Puede GNU Grep generar un grupo seleccionado?

47

¿Es posible usar GNU grep para obtener un grupo coincidente de una expresión?

Ejemplo:

echo "foo 'bar'" | grep -oE "'([^']+)'"

Lo que generaría "'bar'". Pero me gustaría obtener solo "bar", sin tener que enviarlo a través de grep una vez más (es decir, obtener el grupo coincidente). ¿Es eso posible?

Torandi
fuente

Respuestas:

50

Puedes usar sedpara esto. En BSD sed:

echo "foo 'bar'" | sed -E "s/.*'([^']+)'.*/\\1/"

O, sin la -Eopción:

sed "s/.*'\([^']\+\)'.*/\1/"

Esto no funciona para la entrada multilínea. Para eso necesitas:

sed -n "s/.*'\([^']\+\)'.*/\1/p"
jtbandes
fuente
Gracias, se había olvidado de sed. Pero para aclarar, sed no toma el argumento -E ..
Torandi
Hm, lo hace en mi máquina (Mac OS X). Tras un examen más detallado, en la página del manual: "Las opciones -E, -a y -i son extensiones de FreeBSD no estándar y pueden no estar disponibles en otros sistemas operativos".
jtbandes
1
-r parece eso para mí.
Torandi el
1
@jtbandes: No necesita las características extendidas para esta expresión. Solo necesito 3 caracteres de escape para ( ) +usar \( \) \+: Esto es efectivamente lo mismo:sed "s/.*'\([^']\+\)'.*/\1/"
Peter.O
2
Esto no funciona para la entrada multilínea. Para eso necesitas: sed -n "s/.*'\([^']\+\)'.*/\1/p"
phreakhead
28

Si bien grep no puede generar un grupo específico, puede usar aserciones anticipadas y subyacentes para lograr lo que busca:

echo "foo 'bar'" | grep -Po "(?<=')[^']+(?=')"

Aldrik
fuente
8
grep -Pno está disponible en todas las plataformas. Pero si es así, usar mirar hacia adelante / atrás es una muy buena manera de resolver el problema.
Sébastien
1
¿Es grep inteligente con las afirmaciones retrospectivas? ¿Cómo funciona con largas miradas atrás? ¿Está integrando los look-behinds en algún tipo de "árbol de sufijos" con el resto de la expresión regular?
Ross Rogers
3

Puede usar \Kpara restablecer y descartar el texto de coincidencia de la izquierda junto con una búsqueda anticipada que no se agrega al texto de coincidencia:

$ echo "foo 'bar'" | grep -oP "'\K[^']+(?=')"
bar

GNU grep solamente.

Drawk
fuente