¿Cómo extraer texto de una cadena usando sed?


96

Mi cadena de ejemplo es la siguiente:

This is 02G05 a test string 20-Jul-2012

Ahora de la cadena de arriba quiero extraer 02G05. Para eso probé la siguiente expresión regular con sed

$ echo "This is 02G05 a test string 20-Jul-2012" | sed -n '/\d+G\d+/p'

Pero el comando anterior no imprime nada y la razón por la que creo es que no puede hacer coincidir nada con el patrón que proporcioné a sed.

Entonces, mi pregunta es qué estoy haciendo mal aquí y cómo corregirlo.

Cuando pruebo la cadena y el patrón anteriores con python, obtengo mi resultado

>>> re.findall(r'\d+G\d+',st)
['02G05']
>>>

6
Python definitivamente no lo es sed. Sus sabores de expresiones regulares son bastante diferentes.
— tripleee

Respuestas:


92

Es \dposible que el patrón no sea compatible con su sed. Prueba [0-9]o en su [[:digit:]]lugar.

Para imprimir solo la coincidencia real (no toda la línea coincidente), utilice una sustitución.

sed -n 's/.*\([0-9][0-9]*G[0-9][0-9]*\).*/\1/p'

6
Gracias, funcionó bien. Pero tengo una pregunta de por qué .*es necesario con su expresión regular porque cuando lo intento sed -n 's/\([0-9]\+G[0-9]\+\)/\1/p'solo imprime la línea completa.
— RanRag

7
Por eso, ¿no es así? Reemplace lo que venga antes y después de la coincidencia con norhing, luego imprima la línea completa.
— tripleee

1
@tripleee Esto solo imprime 2G05no 02G05. La expresión que funciona es's/.*\([0-9][0-9]G[0-9][0-9]*\).*/\1/p'
— Kshitiz Sharma

1
Eso lo codifica exactamente a dos dígitos. Algo así sed -n 's/\(.*[^0-9]\)\?\([0-9][0-9]*G[0-9][0-9]*\).*/\2/p'sería más general. (Asumo sus sedapoyos \?para cero o una ocurrencia)
— tripleee

Consulte también stackoverflow.com/a/48898886/874188 para saber cómo reemplazar varios otros escapes de Perl comunes como \w,\s , etc.
— tripleee

99

¿Qué tal usar grep -E?

echo "This is 02G05 a test string 20-Jul-2012" | grep -Eo '[0-9]+G[0-9]+'

3
+1 Esto es más simple y también manejará correctamente el caso de múltiples coincidencias en la misma línea. Se sedpodría idear un guión complejo para ese caso, pero ¿para qué molestarse?
— tripleee

egrepPosibilidades de ampliar expresión regular, sedy greputiliza expresiones regulares estándar, egrepo grep -eo sed -Eusan expresión regular extendida, y el código Python en la pregunta utiliza PCRE, (Perl expresiones regulares común) GNU grep puede utilizar PCRE con -Popción.
— Felipe Buccioni

@FelipeBuccioni en realidad debería ser egrepo grep -Eosed -r
— SensorSmith

Para una única (primera) coincidencia, agregue `| head -1` (sin comillas invertidas), según esta respuesta a otra pregunta.
— SensorSmith

1
greptiene -m 1que parar después del primer partido.
— tripleee


5

Prueba esto en su lugar:

echo "This is 02G05 a test string 20-Jul-2012" | sed 's/.* \([0-9]\+G[0-9]\+\) .*/\1/'

Pero tenga en cuenta que si hay dos patrones en una línea, imprimirá el segundo.


O más generalmente el último si hay múltiples coincidencias.
— tripleee

0

Intente usar rextract . Le permitirá extraer texto usando una expresión regular y reformatearlo.

Ejemplo:

$ echo "This is 02G05 a test string 20-Jul-2012" | ./rextract '([\d]+G[\d]+)' '${1}'

2G05

Si esto usa expresiones regulares estándar, los corchetes alrededor \dson completamente superfluos.
— tripleee
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.