Regex que grep números después de una cadena específica

8

Entonces tengo una línea:

ID: 54376

¿Me pueden ayudar a hacer una expresión regular que solo devolvería números sin "ID:"?

NOTA: esta cadena está en un archivo.

Blake Gibbs
fuente

Respuestas:

14

Prueba esto:

grep -oP '(?<=ID: )[0-9]+' file

o:

perl -nle 'print $1 if /ID:.*?(\d+)/' file
Cuonglm
fuente
Gracias por la respuesta, pero no necesito todos los números de un archivo, solo necesito un número que aparece después de la identificación:
Blake Gibbs
Actualicé mi respuesta.
Cuonglm
1
Tenga en cuenta que -oy -Pson extensiones de GNU para grep. -ofunciona también en los BSD. El soporte PCRE con -Pno siempre se compila tampoco.
Matt
4

Use egrepcon -oo grepcon la -Eoopción para obtener solo el segmento coincidente. Use [0-9]como expresión regular para obtener solo números:

grep -Eo [0-9]+ filename
Rohit Jain
fuente
1
El OP necesita que coincida solo después de una cadena específica. Ver el título de la pregunta.
terdon
4

Hay muchas formas de hacer esto. Por ejemplo:

  1. Use GNU grepcon PCRE recientes y haga coincidir los números después de ID::

    grep -oP 'ID:\s*\K\d+' file
    
  2. Use awke imprima el último campo de todas las líneas que comienzan conID:

    awk '/^ID:/{print $NF}' file
    

    Sin embargo, eso también imprimirá campos que no son números, para obtener solo números, y solo en el segundo campo, use

    awk '($1=="ID:" && $2~/^[0-9]+$/){print $2}' file
    
  3. Use GNU grep con Expresiones regulares extendidas y analícelo dos veces:

    grep -Eo '^ID: *[0-9]+' file | grep -o '[0-9]*'
    
terdon
fuente
¡Gracias! ¿Qué \Kestá haciendo en el primer ejemplo?
rnd_d
2
@rnd_d es una construcción de expresiones regulares compatibles con Perl (PCRE) que significa "ignorar todo lo que coincida hasta este momento". Se usa como una mirada retrospectiva, me permite usar -opara imprimir solo la parte coincidente pero también descartar cosas que no me interesan. Comparar echo "foobar" | grep -oP "foobar"yecho "foobar" | grep -oP 'foo\Kbar'
terdon
4
sed -n '/ID: 54376/,${s/[^ 0-9]*//g;/./p}'

Eso imprimirá solo todos los números y espacios que ocurran después ID: 54376en cualquier entrada de archivo.

Acabo de actualizar un poco lo anterior para hacerlo un poco más rápido *y no peliminar líneas en blanco después de eliminar los caracteres que no son {numéricos, espacio}.

Aborda las líneas desde la expresión regular /ID: 54376/ ,hasta la $última y en ellas s///elimina todos los *caracteres o ^no, [^ 0-9]*luego no pborra /ninguna /línea con un .carácter restante.

MANIFESTACIÓN:

{
echo line 
printf 'ID: 54376\nno_nums_or_spaces\n'
printf '%s @nd 0th3r char@cter$ %s\n' $(seq 10)
echo 'ID: 54376'
} | sed -n '/ID 54376/,${s/[^ 0-9]*//g;/./p}'

SALIDA:

 54376
1  03  2
3  03  4
5  03  6
7  03  8
9  03  10
 54376
mikeserv
fuente
1

Usando sed:

{
    echo "ID: 1"
    echo "Line doesn't start with ID: "
    echo "ID: Non-numbers"
    echo "ID: 4"
} | sed -n '/^ID: [0-9][0-9]*$/s/ID: //p'

El -nes "no imprime nada por defecto", /^ID: [0-9][0-9]*$/es "para líneas que coinciden con esta expresión regular" (comienza con "ID:", luego 1 o más dígitos, luego final de línea), y el s/ID: //pes de la forma s/pattern/repl/flags- ssignifica que estás haciendo un sustituto, para reemplazar el patrón "ID: "con texto de reemplazo ""(cadena vacía) usando la pbandera, que significa "imprimir esta línea después de hacer la sustitución".

Salida:

1
4
Godlygeek
fuente
No funcionará si la identificación está presente en el centro de una línea.
Avinash Raj
Tampoco debería, basado en mi lectura de la pregunta. Y no tratar de manejar ese caso prematuramente hace que el código sea más simple y más portátil.
Godlygeek
0

Otro comando de GNU sed,

sed -nr '/ID: [0-9]+/ s/.*ID: +([0-9]+).*/\1/p' file

Imprime cualquier número después ID:

Avinash Raj
fuente
Realmente no necesitas el +. Si la diferencia entre un personaje y 3 caracteres es la secuencia de comandos no funcionen en todas seds probablemente debería hacer: sed -n '/ID: \([0-9][0-9]*\).*/{s//\1/;s/.*[^0-9]//;/./p}'. Su respuesta también pierde el primero ID: [0-9]en una línea que contiene dos ocurrencias de ID: [0-9].
mikeserv
0

Use grep + awk:

  grep "^ID" your_file | awk {'print $2'}

Bono: fácil de leer :)

lirio
fuente
1
No necesitas grepsi lo estás usando awk. awk '/^ID/ { print $2 }'hace lo mismo y evita los problemas de almacenamiento en línea de grep . También es más o menos lo mismo que una de las soluciones en la respuesta de @terdon.
cas