web-dev-qa-db-fra.com

Extraire des nombres d'une chaîne à l'aide de sed et d'expressions régulières

Une autre question pour les experts sed.

J'ai une chaîne représentant un chemin d'accès qui comportera deux nombres. Un exemple est:

./pentaray_run2/Trace_220560.dat

J'ai besoin d'extraire le deuxième de ces nombres - ie 220560

J'ai (avec l'aide des forums) pu extraire tous les nombres ensemble (ie 2220560) avec:

sed "s/[^0-9]//g"

ou extraire uniquement le premier nombre avec:

sed -r 's|^([^.]+).*$|\1|; s|^[^0-9]*([0-9]+).*$|\1|'

Mais ce que je recherche c'est le deuxième numéro !! Toute aide très appréciée.

PS le numéro que je recherche est toujours le deuxième numéro de la chaîne.

19
Steven

est-ce correct?

sed -r 's/.*_([0-9]*)\..*/\1/g'

avec votre exemple:

kent$   echo "./pentaray_run2/Trace_220560.dat"|sed -r 's/.*_([0-9]*)\..*/\1/g'
220560
16
Kent

Vous pouvez extraire les derniers chiffres avec ceci:

sed -e 's/.*[^0-9]\([0-9]\+\)[^0-9]*$/\1/'

Il est plus facile de penser cela à l'envers:

  1. À la fin de la chaîne, faites correspondre zéro ou plusieurs caractères non numériques
  2. Faire correspondre (et capturer) un ou plusieurs caractères numériques
  3. Correspond à au moins un caractère non numérique
  4. Correspond à tous les caractères au début de la chaîne

La partie 3 de la correspondance est l'endroit où la "magie" se produit, mais elle limite également vos correspondances pour avoir au moins un non-chiffre avant le numéro (c'est-à-dire que vous ne pouvez pas faire correspondre une chaîne avec un seul numéro qui est au début de la chaîne, bien qu'il existe une solution simple d'insérer un non-digit au début de la chaîne).

La magie est de contrer la gourmandise de gauche à droite du .* (partie 4). Sans la partie 3, la partie 4 consommerait tout ce qu'elle peut, ce qui inclut les chiffres, mais avec elle, la correspondance s'assure qu'elle s'arrête afin de permettre à au moins un non-chiffre suivi d'un chiffre d'être consommé par les parties 1 et 2, permettant la capture du nombre.

Si grep est le bienvenu:

$ echo './pentaray_run2/Trace_220560.dat' | grep -oP '\d+\D+\K\d+'
220560

Et plus portable avec Perl avec le même regex:

echo './pentaray_run2/Trace_220560.dat' | Perl -lne 'print $& if /\d+\D+\K\d+/'
220560

Je pense que l'approche est plus propre et plus robuste que l'utilisation de sed

7
Gilles Quenot

Cela pourrait fonctionner pour vous (GNU sed):

sed -r 's/([^0-9]*([0-9]*)){2}.*/\2/' file

Cela extrait le deuxième nombre:

sed -r 's/([^0-9]*([0-9]*)){1}.*/\2/' file

et cela extrait le premier.

5
potong