J'ai un fichier, qui contient des données de numéro de téléphone, et aussi des trucs inutiles. J'essaie d'analyser les chiffres, et lorsqu'il n'y a qu'un seul numéro de téléphone/ligne, ce n'est pas un problème. Mais quand j'ai plusieurs numéros, sed correspond au dernier (même si partout où il est dit qu'il ne devrait correspondre qu'au premier motif?), Et je ne peux pas sortir d'autres chiffres ..
Mon data.txt:
bla bla bla NUM:09011111111 bla bla bla bla NUM:08022222222 bla bla bla
Lorsque j'analyse les données, mon idée était d'abord de supprimer tous les "initiaux" "bla bla bla" devant le premier numéro de téléphone (donc je recherche la première occurrence de 'NUM:'), puis je supprime tous les trucs après le numéro de téléphone et obtenez le numéro. Après cela, je veux analyser l'occurrence suivante à partir de la chaîne restante.
Alors maintenant, quand j'essaie de le séduire, j'ai toujours le dernier numéro sur la ligne:
>sed 's/.*NUM://' data.txt
08022222222 bla bla bla
>
Je voudrais principalement comprendre ce qui ne va pas avec ma compréhension du SED. Bien sûr, des suggestions plus efficaces sont les bienvenues! Ma commande sed ne dit-elle pas de remplacer toutes les choses avant 'NUM:' par '' (vide)? Pourquoi correspond-il toujours à la dernière occurrence?
Merci!
Cela pourrait fonctionner pour vous:
echo "bla bla bla NUM:09011111111 bla bla bla bla NUM:08022222222 bla bla bla" |
sed 's/NUM:/\n&/g;s/[^\n]*\n\(NUM:[0-9]*\)[^\n]*/\1 /g;s/.$//'
NUM:09011111111 NUM:08022222222
Le problème que vous rencontrez est de comprendre que le .*
est gourmand, c'est-à-dire qu'il correspond à la correspondance la plus longue pas la première correspondance. En plaçant un caractère unique (\n
sed l'utilise comme délimiteur de ligne, il ne peut donc pas exister dans la ligne) devant la chaîne qui nous intéresse (NUM:...
) et en supprimant tout ce qui n'est pas ce caractère unique [^\n]*
suivi du caractère unique \n
, nous avons effectivement divisé la chaîne en morceaux gérables.
Comme vous le savez maintenant, les expressions rationnelles sed
sont gourmandes et, pour autant que je sache, ne peuvent pas être rendues non gourmandes.
Deux alternatives qui n'ont pas été évoquées jusqu'à présent sont d'utiliser simplement d'autres outils pour ce type de correspondance/extraction.
Vous pouvez utiliser Perl
en remplacement de sed avec le -pe
paramètres. Il prend en charge le ?
modificateur non gourmand:
$ Perl -pe 's/.*?NUM://' data.txt
09011111111 bla bla bla bla NUM:08022222222 bla bla bla
Vous pouvez utiliser le -o
option pour GNU grep pour obtenir uniquement les bits de vos données qui correspondent à l'expression régulière:
$ egrep -o 'NUM:[0-9]*' data.txt
NUM:09011111111
NUM:08022222222
Si un nombre est défini par des chiffres suivant un NUM:
:
sed -n -e 's/$/\n/' -e ':begin' \
-e 's/\(NUM:[0-9][0-9]*\)\(.*\)\n\(.*\)/\2\n\3 \1/' \
-e 'tbegin' -e 's/.*\n //' -e '/NUM/p'
Ce que cela signifie:
\n
à la fin de la ligne pour servir de marqueur.Cela peut également être fait dans l'autre sens, en laissant d'abord tomber les lignes sans chiffres:
sed -e '/NUM/!d' -e 's/$/\n/' -e ':begin' \
-e 's/\(NUM:[0-9][0-9]*\)\(.*\)\n\(.*\)/\2\n\3 \1/' \
-e 'tbegin' -e 's/.*\n //'
Vous pouvez utiliser ce modèle:
sed -r 's/^(.*NUM:)(.*NUM:.*)$/\2/'