Quelle serait la meilleure façon de vérifier si $ 1 est un entier dans / bin / dash?
En bash, je pourrais faire:
[[ $1 =~ ^([0-9]+)$ ]]
Mais cela ne semble pas être conforme à POSIX et le tableau de bord ne prend pas en charge cela
Quelle serait la meilleure façon de vérifier si $ 1 est un entier dans / bin / dash?
En bash, je pourrais faire:
[[ $1 =~ ^([0-9]+)$ ]]
Mais cela ne semble pas être conforme à POSIX et le tableau de bord ne prend pas en charge cela
Réponses:
Les éléments suivants détectent les entiers, positifs ou négatifs, et fonctionnent sous dash
et sont POSIX:
echo "$1" | grep -Eq '^[+-]?[0-9]+$' && echo "It's an integer"
case "${1#[+-]}" in
''|*[!0-9]*)
echo "Not an integer" ;;
*)
echo "Integer" ;;
esac
Ou, avec un peu d'utilisation de la :
commande (nop):
! case ${1#[+-]} in *[!0-9]*) :;; ?*) ! :;; esac && echo Integer
Que dash
, bash
, ksh
, zsh
, POSIX sh
, ou posh
( "une remise en marche de la coque Bourne" sh
); la case
construction est la plus largement disponible et la plus fiable:
case $1 in (*[!0-9]*|"") false ;; (*) true ;; esac
dash
? Cela fonctionne pour moi sous bash
mais pas dash
.
dash
; pour interroger le résultat, j'ai ajouté echo $?
après la commande de cas.
posh
("une réimplémentation du shell Bourne") n'a pas non plus de problème avec cette solution.
case
; une raison est le bogue que vous décrivez, un autre qui, dans les éditeurs qui ont des fonctionnalités qui reposent sur des parenthèses correspondantes (vim), il offre un bien meilleur support, et non des moindres, je trouve personnellement mieux lisible de les faire correspondre. - WRT posh
étant POSIX; eh bien, la citation de la page de manuel que j'ai donnée suggérait autre chose, mais on ne peut pas s'appuyer sur de telles déclarations informelles de toute façon, je suppose. Le vieux bourne shell n'est de toute façon plus aussi important maintenant que nous sommes à l'ère POSIX.
Vous pouvez utiliser le -eq
test sur la chaîne, avec lui-même:
$ dash -c 'a="a"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
dash: 1: [: Illegal number: a
not a number
$ dash -c 'a="0xa"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
dash: 1: [: Illegal number: 0xa
not a number
$ dash -c 'a="-1"; if [ "$a" -eq "$a" ] ; then echo number; else echo not a number; fi'
number
Si le message d'erreur est un problème, redirigez la sortie d'erreur vers /dev/null
:
$ dash -c 'a="0xa"; [ "$a" -eq "$a" ] 2>/dev/null|| echo no'
no
" 023 "
c'est un chiffre. Notez qu'il fonctionne avec dash, mais pas tous les autres shells POSIX car le comportement n'est pas spécifié si les opérandes sont des entiers décimaux de note. Par exemple avec ksh, cela dirait que SHLVL
ou 1+1
est un nombre.
Essayez de l'utiliser comme une expansion arithmétique et voyez si cela fonctionne. En fait, vous devez être un peu plus strict que cela, car les extensions arithmétiques ignoreraient les espaces de début et de fin, par exemple. Faites donc une expansion arithmétique et assurez-vous que le résultat développé correspond exactement à la variable d'origine.
check_if_number()
{
if [ "$1" = "$((${1}))" ] 2>/dev/null; then
echo "Number!"
else
echo "not a number"
fi
}
Cela accepterait également les nombres négatifs - si vous voulez vraiment les exclure, ajoutez un chèque supplémentaire pour $((${1} >= 0))
.
[[
$(( ... ))
? Si c'est le cas, ma réponse devrait toujours être matériellement correcte, il me suffit d'ajouter quelques citations supplémentaires.
check_if_number 1.2
et la fonction est revenue: dash: 3: arithmetic expression: expecting EOF: "1.2"
Peut-être avec expr
?
if expr match "$1" '^\([0-9]\+\)$' > /dev/null; then
echo "integer"
else
echo "non-integer"
fi
match
ne \+
sont POSIX. Cela signifierait également que 0 n'est pas un nombre. Vous voulezexpr "x$1" : 'x[0-9]\{1,\}$'
Dans le système POSIX, vous pouvez utiliser expr :
$ a=a
$ expr "$a" - 0 >/dev/null 2>&1
$ [ "$?" -lt 2 ] && echo Integer || echo Not Integer
expr
implémentations diront que 999999999999999999999 n'est pas un entier. POSIX ne donne aucune garantie que cela fonctionnera. En pratique, sur un système GNU au moins, il dira que la "longueur" est un entier.
expr 9999999999999999999 + 0
me donne un statut 3 de sortie et expr -12 + 0
et expr length + 0
me donner un statut de sortie 0 avec GNU expr ( + string
forces string
à considérer comme une chaîne avec GNU expr
. expr "$a" - 0
Fonctionnerait mieux).
-12
c'est un entier valide, et a 9999999999999999999
donné un débordement.
Voici une fonction simple utilisant la même méthode que la réponse de muru :
IsInteger() # usage: IsInteger string
{ # returns: flag
[ "$1" -eq "$1" ] 2> /dev/null
}
Exemple:
p= n=2a3; IsInteger $n || p="n't" ; printf "'%s' is%s an integer\n" "$n" "$p"
p= n=23; IsInteger $n || p="n't" ; printf "'%s' is%s an integer\n" "$n" "$p"
Production:
'2a3' isn't an integer
'23' is an integer
foo\n123\nbar
n'est pas un entier, mais réussirait ce test.