Vérifier si un numéro d'entrée est un entier


31

J'essaie de vérifier si une entrée est un entier et je l'ai parcouru cent fois, mais je ne vois pas l'erreur ici. Hélas, cela ne fonctionne pas, il déclenche l'instruction if pour toutes les entrées (chiffres / lettres)

read scale
if ! [[ "$scale" =~ "^[0-9]+$" ]]
        then
            echo "Sorry integers only"
fi

J'ai joué avec les citations mais soit je l'ai raté, soit ça n'a rien fait. Qu'est-ce que je fais mal? Existe-t-il un moyen plus simple de tester si une entrée n'est qu'un INTEGER?

Réponses:


25

Supprimer les devis

if ! [[ "$scale" =~ ^[0-9]+$ ]]
    then
        echo "Sorry integers only"
fi


Il y a donc un bug. Avec des guillemets, l'expression rationnelle est traitée comme une chaîne littérale. On peut vérifier cela avecscale='^[0-9]+$'; [[ "$scale" == "^[0-9]+$" ]] && echo equal || echo "not equal"
jimmij

15

Utilisez l' -eqopérateur de la commande de test :

read scale
if ! [ "$scale" -eq "$scale" ] 2> /dev/null
then
    echo "Sorry integers only"
fi

Il fonctionne non seulement dans bashmais aussi dans n'importe quel shell POSIX. De la documentation de test POSIX :

n1 -eq  n2
    True if the integers n1 and n2 are algebraically equal; otherwise, false.

qui vérifie si c'est n'importe quel nombre, pas seulement des entiers
lonewarrior556

2
@ lonewarrior556: Cela ne fonctionne que pour un entier, voir: pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html . Je suppose que vous avez dit pour n'importe quel nombre parce que vous utilisez le nouveau test [[au lieu de l'ancien test [comme le mien.
cuonglm

Bonne idée mais un peu bruyante. Je préfère ne pas avoir à rediriger les erreurs vers dev null.
Wildcard

2
@Wildcard: Oui, nous le payons pour la portabilité.
cuonglm

8

Pour les entiers non signés, j'utilise:

read -r scale
[ -z "${scale//[0-9]}" ] && [ -n "$scale" ] || echo "Sorry integers only"

Tests:

$ ./test.sh
7
$ ./test.sh
   777
$ ./test.sh
a
Sorry integers only
$ ./test.sh
""
Sorry integers only
$ ./test.sh

Sorry integers only

1
J'aime celui-ci car il est fait avec des builtins, rapide et semble assez posix ... J'ai essayé un vieux shell (bash 2.0.5) et cela fonctionne parfaitement.
Olivier Dulac

Qu'en est-il des espaces à l'intérieur de l'argument? Comme «086» .
0andriy

@ 0andriy Voir le deuxième test.
raciasolvo

8

Comme l'OP ne semble vouloir que des entiers positifs:

[ "$1" -ge 0 ] 2>/dev/null

Exemples:

$ is_positive_int(){ [ "$1" -ge 0 ] 2>/dev/null && echo YES || echo no; }
$ is_positive_int word
no
$ is_positive_int 2.1
no
$ is_positive_int -3
no
$ is_positive_int 42
YES

Notez qu'un seul [test est requis:

$ [[ "word" -eq 0 ]] && echo word equals zero || echo nope
word equals zero
$ [ "word" -eq 0 ] && echo word equals zero || echo nope
-bash: [: word: integer expression expected
nope

En effet, le déréférencement se produit avec [[:

$ word=other
$ other=3                                                                                                                                                                                  
$ [[ $word -eq 3 ]] && echo word equals other equals 3
word equals other equals 3

c'est la vraie réponse ... d'autres ont échoué
Scott Stensland

3
( scale=${scale##*[!0-9]*}
: ${scale:?input must be an integer}
) || exit

Cela vérifie et génère votre erreur.


OPTINDest bon ici aussi. juste saiyan.
mikeserv

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.