Regex qui grep les nombres après une chaîne spécifique

8

J'ai donc une ligne:

ID: 54376

Pouvez-vous m'aider à créer une expression régulière qui ne renverrait que des chiffres sans "ID:"?

REMARQUE: cette chaîne se trouve dans un fichier.

Blake Gibbs
la source

Réponses:

14

Essaye ça:

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

ou:

perl -nle 'print $1 if /ID:.*?(\d+)/' file
cuonglm
la source
Merci pour la réponse, mais je n'ai pas besoin de tous les numéros d'un fichier, il suffit d'un numéro qui se produit après l'ID:
Blake Gibbs
Mis à jour ma réponse.
cuonglm
1
Notez que -oet -Psont des extensions GNU pour grep. -ofonctionne également sur les BSD. La prise en charge de PCRE avec -Pn'est pas toujours compilée non plus.
Matt
4

Utilisez egrepavec -oou grepavec l' -Eooption pour obtenir uniquement le segment correspondant. Utilisez [0-9]comme expression régulière pour obtenir uniquement des nombres:

grep -Eo [0-9]+ filename
Rohit Jain
la source
1
L'OP en a besoin pour correspondre uniquement après une chaîne spécifique. Voir le titre de la question.
terdon
4

Il y a plusieurs façons de procéder. Par exemple:

  1. Utilisez GNU grepavec des PCRE récents et faites correspondre les nombres après ID::

    grep -oP 'ID:\s*\K\d+' file
    
  2. Utilisez awket imprimez simplement le dernier champ de toutes les lignes commençant parID:

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

    Cela imprimera également les champs qui ne sont pas des nombres, pour obtenir des nombres uniquement et uniquement dans le deuxième champ, utilisez

    awk '($1=="ID:" && $2~/^[0-9]+$/){print $2}' file
    
  3. Utilisez GNU grep avec les expressions régulières étendues et analysez-le deux fois:

    grep -Eo '^ID: *[0-9]+' file | grep -o '[0-9]*'
    
terdon
la source
Merci! Que \Kfait-on dans le premier exemple?
rnd_d
2
@rnd_d c'est une construction d'expressions régulières compatibles Perl (PCRE) qui signifie "ignorer tout ce qui correspond à ce point". Il est utilisé comme un lookbehind, il me permet -ode n'imprimer que la partie correspondante mais aussi de jeter les choses qui ne m'intéressent pas. Comparer echo "foobar" | grep -oP "foobar"etecho "foobar" | grep -oP 'foo\Kbar'
terdon
4
sed -n '/ID: 54376/,${s/[^ 0-9]*//g;/./p}'

Cela n'imprimera que tous les nombres et espaces survenant après ID: 54376dans n'importe quelle entrée de fichier.

Je viens de mettre à jour ce qui précède un peu pour le rendre un peu plus rapide avec *et pour ne pas pimprimer de lignes vides après avoir supprimé les caractères non {numériques, espace}.

Il aborde des lignes de regex à /ID: 54376/ ,travers la $dernière et les s///supprime tous ou les *caractères ^ne [^ 0-9]*puis prints /une /ligne avec un .caractère restant.

DÉMO:

{
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}'

PRODUCTION:

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

Utilisation de 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'

La valeur -n"n'imprime rien par défaut", la valeur /^ID: [0-9][0-9]*$/"pour les lignes correspondant à cette expression régulière" (commence par "ID:", puis 1 ou plusieurs chiffres, puis la fin de la ligne), et s/ID: //pla forme est s/pattern/repl/flags- ssignifie que nous fais un substitut, pour remplacer le motif "ID: "par du texte de remplacement ""(chaîne vide) en utilisant le pdrapeau, ce qui signifie "imprimer cette ligne après avoir fait la substitution".

Production:

1
4
godlygeek
la source
Cela ne fonctionnera pas si l'ID est présent au centre d'une ligne.
Avinash Raj
Cela ne devrait pas non plus, d'après ma lecture de la question. Et ne pas essayer de gérer prématurément ce cas rend le code plus simple et plus portable.
godlygeek
0

Une autre commande GNU sed,

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

Il imprime n'importe quel nombre après ID:

Avinash Raj
la source
Vous n'avez vraiment pas besoin de ça +. Si la différence entre un caractère et 3 caractères est votre script ne fonctionne pas dans tous les seds vous devriez probablement faire: sed -n '/ID: \([0-9][0-9]*\).*/{s//\1/;s/.*[^0-9]//;/./p}'. Votre réponse manque également la première ID: [0-9]d'une ligne contenant deux occurrences de ID: [0-9].
mikeserv
0

Utilisez grep + awk:

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

Bonus: facile à lire :)

lis
la source
1
Vous n'avez pas besoin grepsi vous utilisez awk. awk '/^ID/ { print $2 }'fait la même chose et évite les problèmes de mise en mémoire tampon des lignes grep . C'est aussi à peu près la même chose que l'une des solutions dans la réponse de @ terdon.
cas