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?

lonewarrior556
la source

Réponses:

25

Supprimer les devis

if ! [[ "$scale" =~ ^[0-9]+$ ]]
    then
        echo "Sorry integers only"
fi
jimmij
la source
stackoverflow.com/questions/806906/… avait les citations à l'envers
lonewarrior556
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.
cuonglm
la source
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
raciasolvo
la source
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
Tom Hale
la source
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.

mikeserv
la source
OPTINDest bon ici aussi. juste saiyan.
mikeserv