Bash: comment obtenir le premier nombre qui se produit dans le contenu d'une variable

8

comment obtenir le premier nombre de variables

J'ai une variable:

STR="My horse weighs 3000 kg but the car weighs more"
STR="Maruska found 000011 mushrooms but only 001 was not with meat"
STR="Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK"

J'ai besoin d'obtenir les chiffres:

3000
11
20
Rui F Ribeiro
la source

Réponses:

7

Avec gawk, définissez le séparateur d'enregistrement RSsur une séquence de chiffres. Le texte correspondant au RSmotif peut être récupéré via RT. Ajouter 0à RTpour le forcer à un nombre (supprimant ainsi les zéros de tête). Quitter dès que la première instance est imprimée

awk -v RS=[0-9]+ '{print RT+0;exit}' <<< "$STR"

Ou voici une solution bash

shopt -s extglob
read -r Z _ <<< "${STR//[^[:digit:] ]/}"
echo ${Z##+(0)}
iruvar
la source
Agréable. Voulez-vous élaborer?
jasonwryan
Je ne comprends pas. Qu'est-ce que je fais mal (avec la version awk)? gist.github.com/jamiejackson/d92750cc42442a527c6b94499a13bc79
Jamie Jackson
@JamieJackson, assurez-vous que vous exécutez GNU awk aka gawk
iruvar
5

Voici une façon de procéder:

echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'

Tester:

$ STR="My horse weighs 3000 kg but the car weighs more"
$ echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'
3000

$ STR="Maruska found 000011 mushrooms but only 001 was not with meat"
$ echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'
11

$ STR="Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK"
$ echo $STR | grep -o -E '[0-9]+' | head -1 | sed -e 's/^0\+//'
20
cuonglm
la source
Quel est le but de sedla fin? Il semble qu'avant d'entrer dans sed, nous avons déjà le résultat que nous voulons.
Michael
Non, vous avez pour # 2 000011pour lequel vous devez supprimer les zéros de plomb. Mais vous pourriez simplifier en faisant correspondre [1-9][0-9]*ce qui supprimerait les zéros de tête dès le début: echo $STR | grep -o -E '[1-9][0-9]*'
CCH
2

Si votre implémentation de grepn'a pas -oou si vous n'utilisez pas Bash, vous pouvez effectuer les opérations suivantes:

printf "%.0f\n" $(printf "%s" "$string"|sed  's/^[^0-9]*//;s/[^0-9].*$//')
Joseph R.
la source
2
#!/bin/bash

string="My horse weighs 3000 kg but the car weighs more"

if [[ $string =~ ^([a-zA-Z\ ]*)([0-9]*)(.*)$ ]]
then
    echo ${BASH_REMATCH[1]}
fi  
philippe
la source
1
L'indice devrait être 2 au lieu de 1. Mais vous n'avez vraiment pas besoin de ce complexe d'une expression régulière. Il échouerait de toute façon s'il y avait d'autres caractères dans la chaîne.
pause jusqu'à nouvel ordre.
2

J'ai placé vos chaînes dans un tableau afin qu'il puisse être facilement itéré pour cette démonstration.

Cela utilise la correspondance d'expression régulière intégrée de Bash.

Seul un modèle très simple est requis. Il est recommandé d'utiliser une variable pour conserver le motif au lieu de l'incorporer directement dans le test de correspondance. C'est essentiel pour des motifs plus complexes.

str[0]="My horse weighs 3000 kg but the car weighs more"
str[1]="Maruska found 000011 mushrooms but only 001 was not with meat"
str[2]="Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK"

patt='([[:digit:]]+)'

for s in "${str[@]}"; do [[ $s =~ $patt ]] && echo "[${BASH_REMATCH[1]}] - $s"; done

J'ai inclus les crochets uniquement pour compenser visuellement les chiffres.

Production:

[3000] - My horse weighs 3000 kg but the car weighs more
[000011] - Maruska found 000011 mushrooms but only 001 was not with meat
[0000020] - Yesterday I almost won the lottery 0000020 CZK but in the end it was only 05 CZK

Pour obtenir les chiffres sans les zéros non significatifs, le moyen le plus simple consiste à forcer une conversion en base 10.

echo "$(( 10#${BASH_REMATCH[1]} ))"

En remplaçant cela, la sortie ressemble à ce que vous avez demandé:

3000
11
20
En pause jusqu'à nouvel ordre.
la source
1

Recherchez les expressions régulières et man grep.

echo $STR | grep -o [0-9]*

et pour supprimer les zéros non significatifs, traitez-le comme un nombre:

LIT=$(echo $STR | grep -o [0-9]*)
VAL=$(expr $LIT + 0)
echo $VAL
Sven
la source
Votre solution échoue avec des variables contenant deux nombres ou le nombre de remplissage zéro.
cuonglm