¿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.