Je n'arrive pas à comprendre comment m'assurer qu'un argument transmis à mon script est un nombre ou non.
Tout ce que je veux faire est quelque chose comme ça:
test *isnumber* $1 && VAR=$1 || echo "need a number"
De l'aide?
Une approche consiste à utiliser une expression régulière, comme ceci:
re='^[0-9]+$'
if ! [[ $yournumber =~ $re ]] ; then
echo "error: Not a number" >&2; exit 1
fi
Si la valeur n'est pas nécessairement un entier, envisagez de modifier l'expression rationnelle de manière appropriée. par exemple:
^[0-9]+([.][0-9]+)?$
... ou, pour gérer les chiffres avec un signe:
^[+-]?[0-9]+([.][0-9]+)?$
Sans bashismes (fonctionne même dans le System V sh),
case $string in
''|*[!0-9]*) echo bad ;;
*) echo good ;;
esac
Cela rejette les chaînes vides et les chaînes ne contenant pas de chiffres, acceptant tout le reste.
Les nombres négatifs ou à virgule flottante nécessitent un travail supplémentaire. Une idée est d'exclure -
/.
dans le premier "mauvais" motif et d'ajouter d'autres "mauvais" motifs contenant leurs utilisations inappropriées (?*-*
/*.*.*
)
La solution suivante peut également être utilisée dans des shells de base tels que Bourne sans avoir besoin d'expressions régulières. Fondamentalement, toute opération d'évaluation de valeur numérique utilisant des non-nombres entraînera une erreur qui sera implicitement considérée comme fausse dans Shell:
"$var" -eq "$var"
un péché:
#!/bin/bash
var=a
if [ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null; then
echo number
else
echo not a number
fi
Vous pouvez également tester pour $? le code retour de l'opération qui est plus explicite:
[ -n "$var" ] && ["$var" -eq "$var"] 2>/dev/null
if [ $? -ne 0 ]; then
echo $var is not number
fi
La redirection d'erreur standard permet de masquer le message "expression entière attendue" que bash affiche au cas où nous n'aurions pas de numéro.
MISES EN GARDE(merci aux commentaires ci-dessous):
[[ ]]
au lieu de [ ]
sera toujours évalué à true
true
bash: [[: 1 a: syntax error in expression (error token is "a")
bash: [[: i: expression recursion level exceeded (error token is "i")
, est générée.Ceci teste si un nombre est un entier non négatif et est indépendant du shell (c'est-à-dire sans bashismes) et utilise uniquement les fonctions intégrées du shell:
[ -z "${num##[0-9]*}" ] && echo "is a number" || echo "is not a number";
BUT IS WRONG.
Comme jilles commenté et suggéré dans sa réponse c'est la bonne façon de le faire en utilisant des motifs Shell.
[ ! -z "${num##*[!0-9]*}" ] && echo "is a number" || echo "is not a number";
Personne n'a suggéré de bash correspondance étendue de motifs :
[[ $1 == ?(-)+([0-9]) ]] && echo "$1 is an integer"
Je suis surpris par les solutions qui analysent directement les formats de nombres dans Shell . Shell ne convient pas à cela. Il s'agit d'un DSL permettant de contrôler les fichiers et les processus.
isdecimal() {
# filter octal/hex/ord()
num=$(printf '%s' "$1" | sed "s/^0*\([1-9]\)/\1/; s/'/^/")
test "$num" && printf '%f' "$num" >/dev/null 2>&1
}
Remplacez '% f' par le format que vous souhaitez.
Je regardais les réponses et ... je me suis rendu compte que personne ne pensait aux nombres FLOAT (avec point)!
Utiliser grep est très bien aussi.
- E signifie expression rationnelle étendue
- q signifie calme (ne pas écho)
- qE est la combinaison des deux.
Pour tester directement en ligne de commande:
$ echo "32" | grep -E ^\-?[0-9]?\.?[0-9]+$
# answer is: 32
$ echo "3a2" | grep -E ^\-?[0-9]?\.?[0-9]+$
# answer is empty (false)
$ echo ".5" | grep -E ^\-?[0-9]?\.?[0-9]+$
# answer .5
$ echo "3.2" | grep -E ^\-?[0-9]?\.?[0-9]+$
# answer is 3.2
Utiliser dans un script bash:
check=`echo "$1" | grep -E ^\-?[0-9]*\.?[0-9]+$`
if [ "$check" != '' ]; then
# it IS numeric
echo "Yeap!"
else
# it is NOT numeric.
echo "nooop"
fi
Pour faire correspondre les entiers JUST, utilisez ceci:
# change check line to:
check=`echo "$1" | grep -E ^\-?[0-9]+$`
Juste un suivi de @mary. Mais parce que je n'ai pas assez de représentants, je ne pouvais pas poster ceci en tant que commentaire sur ce post. Quoi qu'il en soit, voici ce que j'ai utilisé:
isnum() { awk -v a="$1" 'BEGIN {print (a == a + 0)}'; }
La fonction retournera "1" si l'argument est un nombre, sinon il retournera "0". Cela fonctionne pour les entiers ainsi que les flottants. L'utilisation est quelque chose comme:
n=-2.05e+07
res=`isnum "$n"`
if [ "$res" == "1" ]; then
echo "$n is a number"
else
echo "$n is not a number"
fi
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_03.html
Vous pouvez également utiliser les classes de caractères de bash.
if [[ $VAR = *[[:digit:]]* ]]; then
echo "$VAR is numeric"
else
echo "$VAR is not numeric"
fi
Les chiffres incluent l'espace, le point décimal et "e" ou "E" pour les virgules flottantes.
Mais, si vous spécifiez un nombre hexadécimal de style C, c'est-à-dire "0xffff" ou "0XFFFF", [[: digit:]] renvoie la valeur true. Un piège ici, bash vous permet de faire quelque chose comme "0xAZ00" et de le compter comme un chiffre (n'est-ce pas un bizarre bizarre de compilateurs GCC qui vous permettait d'utiliser la notation 0x pour des bases autres que 16 ???? )
Vous voudrez peut-être tester "0x" ou "0X" avant de vérifier s'il s'agit d'un nombre numérique si votre entrée est complètement non fiable, sauf si vous souhaitez accepter les nombres hexadécimaux. Cela serait accompli par:
if [[ ${VARIABLE:1:2} = "0x" ]] || [[ ${VARIABLE:1:2} = "0X" ]]; then echo "$VAR is not numeric"; fi
Vieille question, mais je voulais juste ajouter ma solution. Celui-ci ne nécessite aucune astuce Shell étrange, ou s'appuie sur quelque chose qui n'a pas été autour depuis toujours.
if [ -n "$(printf '%s\n' "$var" | sed 's/[0-9]//g')" ]; then
echo 'is not numeric'
else
echo 'is numeric'
fi
Fondamentalement, il supprime simplement tous les chiffres de l'entrée et s'il ne vous reste qu'une chaîne de longueur non nulle, il ne s'agit pas d'un nombre.
test -z "${i//[0-9]}" && echo digits || echo no no no
${i//[0-9]}
remplace tout chiffre de la valeur de $i
par une chaîne vide, voir man -P 'less +/parameter\/' bash
. -z
vérifie si la chaîne résultante a une longueur nulle.
si vous souhaitez également exclure le cas où $i
est vide, vous pouvez utiliser l'une de ces constructions:
test -n "$i" && test -z "${i//[0-9]}" && echo digits || echo not a number
[[ -n "$i" && -z "${i//[0-9]}" ]] && echo digits || echo not a number
[[ $1 =~ ^-?[0-9]+$ ]] && echo "number"
N'oubliez pas -
pour inclure des nombres négatifs!
Je ne peux pas encore commenter, alors je vais ajouter ma propre réponse, qui est une extension de la réponse de Glenn Jackman en utilisant le filtrage par motif bash.
Mon besoin initial était d'identifier les nombres et de distinguer les nombres entiers et les flottants. Les définitions de fonction déduites à:
function isInteger() {
[[ ${1} == ?(-)+([0-9]) ]]
}
function isFloat() {
[[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
}
J'ai utilisé les tests unitaires (avec shUnit2) pour valider mes patterns qui ont fonctionné comme prévu:
oneTimeSetUp() {
int_values="0 123 -0 -123"
float_values="0.0 0. .0 -0.0 -0. -.0 \
123.456 123. .456 -123.456 -123. -.456
123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
}
testIsIntegerIsFloat() {
local value
for value in ${int_values}
do
assertTrue "${value} should be tested as integer" "isInteger ${value}"
assertFalse "${value} should not be tested as float" "isFloat ${value}"
done
for value in ${float_values}
do
assertTrue "${value} should be tested as float" "isFloat ${value}"
assertFalse "${value} should not be tested as integer" "isInteger ${value}"
done
}
Remarques: Le modèle isFloat peut être modifié pour être plus tolérant vis-à-vis du point décimal (@(.,)
) et du symbole E (@(Ee)
). Mes tests unitaires testent uniquement les valeurs entières ou flottantes, mais aucune entrée non valide.
Je voudrais essayer ceci:
printf "%g" "$var" &> /dev/null
if [[ $? == 0 ]] ; then
echo "$var is a number."
else
echo "$var is not a number."
fi
Remarque: ceci reconnaît nan et inf comme nombre.
Le moyen le plus simple est de vérifier s’il contient des caractères non numériques. Vous remplacez tous les caractères numériques par rien et vérifiez la longueur. S'il y a de la longueur, ce n'est pas un nombre.
if [[ ! -n ${input//[0-9]/} ]]; then
echo "Input Is A Number"
fi
Une réponse claire a déjà été donnée par @charles Dufy et d'autres . Une solution pure bash utiliserait ce qui suit:
string="-12,345"
if [[ "$string" =~ ^-?[0-9]+[.,]?[0-9]*$ ]]
then
echo $string is a number
else
echo $string is not a number
fi
Bien que pour les nombres réels, il n'est pas obligatoire d'avoir un nombre avant le point radix .
Pour fournir une prise en charge plus complète des nombres flottants et de la notation scientifique (de nombreux programmes en C/Fortran ou exporteront les flottants de cette façon), un ajout utile à cette ligne serait le suivant:
string="1.2345E-67"
if [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]?-?[0-9]+$ ]]
then
echo $string is a number
else
echo $string is not a number
fi
Ceci conduit donc à un moyen de différencier les types de nombre, si vous recherchez un type spécifique:
string="-12,345"
if [[ "$string" =~ ^-?[0-9]+$ ]]
then
echo $string is an integer
Elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*$ ]]
then
echo $string is a float
Elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]-?[0-9]+$ ]]
then
echo $string is a scientific number
else
echo $string is not a number
fi
Note: Nous pourrions lister les exigences syntaxiques pour la notation décimale et scientifique, l'une étant d'autoriser la virgule comme point radix, ainsi que ".". Nous affirmerions alors qu'il ne doit exister qu'un seul point de base. Il peut y avoir deux signes +/- dans un [Ee] float. J'ai appris un peu plus de règles grâce au travail d'Aulu et j'ai testé contre de mauvaises chaînes telles que '' '-' '-E-1' '0-0'. Voici mes outils regex/substring/expr qui semblent tenir le coup:
parse_num() {
local r=`expr "$1" : '.*\([.,]\)' 2>/dev/null | tr -d '\n'`
nat='^[+-]?[0-9]+[.,]?$' \
dot="${1%[.,]*}${r}${1##*[.,]}" \
float='^[\+\-]?([.,0-9]+[Ee]?[-+]?|)[0-9]+$'
[[ "$1" == $dot ]] && [[ "$1" =~ $float ]] || [[ "$1" =~ $nat ]]
} # usage: parse_num -123.456
J'utilise expr . Il renvoie un non-zéro si vous essayez d'ajouter un zéro à une valeur non numérique:
if expr -- "$number" + 0 > /dev/null 2>&1
then
echo "$number is a number"
else
echo "$number isn't a number"
fi
Il serait peut-être possible d'utiliser bc si vous avez besoin de non-entiers, mais je ne crois pas que bc
a tout à fait le même comportement. L'ajout de zéro à un non-nombre vous donne zéro et il renvoie également une valeur de zéro. Peut-être pouvez-vous combiner bc
et expr
. Utilisez bc
pour ajouter zéro à $number
. Si la réponse est 0
, essayez alors expr
pour vérifier que $number
n'est pas nul.
Comme je devais modifier cela dernièrement et aimer de karttu appoach avec le test unitaire le plus. J'ai révisé le code et ajouté d'autres solutions, essayez-le vous-même pour voir les résultats:
#!/bin/bash
# N={0,1,2,3,...} by syntaxerror
function isNaturalNumber()
{
[[ ${1} =~ ^[0-9]+$ ]]
}
# Z={...,-2,-1,0,1,2,...} by karttu
function isInteger()
{
[[ ${1} == ?(-)+([0-9]) ]]
}
# Q={...,-½,-¼,0.0,¼,½,...} by karttu
function isFloat()
{
[[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
}
# R={...,-1,-½,-¼,0.E+n,¼,½,1,...}
function isNumber()
{
isNaturalNumber $1 || isInteger $1 || isFloat $1
}
bools=("TRUE" "FALSE")
int_values="0 123 -0 -123"
float_values="0.0 0. .0 -0.0 -0. -.0 \
123.456 123. .456 -123.456 -123. -.456 \
123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
false_values="blah meh mooh blah5 67mooh a123bc"
for value in ${int_values} ${float_values} ${false_values}
do
printf " %5s=%-30s" $(isNaturalNumber $value) ${bools[$?]} $(printf "isNaturalNumber(%s)" $value)
printf "%5s=%-24s" $(isInteger $value) ${bools[$?]} $(printf "isInteger(%s)" $value)
printf "%5s=%-24s" $(isFloat $value) ${bools[$?]} $(printf "isFloat(%s)" $value)
printf "%5s=%-24s\n" $(isNumber $value) ${bools[$?]} $(printf "isNumber(%s)" $value)
done
So isNumber () inclut des tirets, des virgules et des notations exponentielles et renvoie donc TRUE sur les entiers & floats, tandis que isFloat () renvoie FALSE sur les valeurs entières et isInteger () FALSE sur des flotteurs. Pour votre commodité, tous comme un seul paquebot:
isNaturalNumber() { [[ ${1} =~ ^[0-9]+$ ]]; }
isInteger() { [[ ${1} == ?(-)+([0-9]) ]]; }
isFloat() { [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]; }
isNumber() { isNaturalNumber $1 || isInteger $1 || isFloat $1; }
Cela peut être réalisé en utilisant grep
pour voir si la variable en question correspond à une expression régulière étendue.
1120
:yournumber=1120
if [ $(echo "$yournumber" | grep -qE '^[0-9]+$'; echo $?) -ne "0" ]; then
echo "Error: not a number."
else
echo "Valid number."
fi
Sortie: Valid number.
1120a
non entier:yournumber=1120a
if [ $(echo "$yournumber" | grep -qE '^[0-9]+$'; echo $?) -ne "0" ]; then
echo "Error: not a number."
else
echo "Valid number."
fi
Sortie: Error: not a number.
grep
, -E
nous permet d'utiliser l'expression régulière étendue '^[0-9]+$'
. Cette expression régulière signifie que la variable doit uniquement []
contenir les nombres 0-9
zéro à neuf du ^
commençant à la fin $
de la variable et doit comporter au moins +
un caractère.grep
, le commutateur silencieux -q
désactive toute sortie, qu’il trouve ou non quelque chose.$?
est le statut de sortie de la commande exécutée précédemment. Le statut de sortie 0
signifie succès et tout ce qui est supérieur signifie une erreur. La commande grep
a le statut de sortie 0
si elle trouve une correspondance et 1
sinon.$()
est un sous-shell qui nous permet d'exécuter une autre commande puis d'utiliser la sortie.Donc, en mettant tout cela ensemble, dans un sous-shell $()
, nous echo
la variable $yournumber
et |
nous le canalisons vers grep
qui avec le commutateur -q
correspond silencieusement à l'expression régulière -E
étendue '^[0-9]+$'
. Nous avons ensuite echo
le statut de sortie $?
, qui serait 0
si grep
a trouvé une correspondance et 1
s’il ne l’a pas été.
Maintenant, en dehors du sous-shell $()
et dans la condition if
, nous prenons la sortie, soit 0
, soit 1
du sous-shell $()
, et vérifions si elle est -ne
différente de "0"
. Si elle ne correspond pas, l'état de sortie sera 1
, ce qui ne correspond pas à "0"
. Ensuite, nous allons echo "Error: not a number."
. Si la correspondance est réussie, la sortie du statut de sortie serait 0
, ce qui correspond à "0"
et, dans le cas contraire, nous echo "Valid number."
.
Nous pouvons simplement changer l'expression régulière de '^[0-9]+$'
à '^[0-9]*+\.?[0-8]+$'
pour les floats ou les doubles.
1120.01
:yournumber=1120.01
if [ $(echo "$yournumber" | grep -qE '^[0-9]*+\.?[0-8]+$'; echo $?) -ne "0" ]; then
echo "Error: not a number."
else
echo "Valid number."
fi
Sortie: Valid number.
11.20.01
:yournumber=11.20.01
if [ $(echo "$yournumber" | grep -qE '^[0-9]*+\.?[0-8]+$'; echo $?) -ne "0" ]; then
echo "Error: not a number."
else
echo "Valid number."
fi
Sortie: Error: not a number.
Pour autoriser les nombres entiers négatifs, modifiez simplement l'expression régulière de '^[0-9]+$'
à '^\-?[0-9]+$'
.
Pour autoriser les doublons ou les flottants négatifs, modifiez simplement l'expression régulière de '^[0-9]*+\.?[0-8]+$'
à '^\-?[0-9]*+\.?[0-8]+$'
.
A fait la même chose ici avec une expression régulière qui teste la partie entière et la partie décimale, séparées par un point.
re="^[0-9]*[.]{0,1}[0-9]*$"
if [[ $1 =~ $re ]]
then
echo "is numeric"
else
echo "Naahh, not numeric"
fi
J'ai essayé la recette d'ultrasawblade car elle me semblait la plus pratique et ne pouvait pas la faire fonctionner. En fin de compte, j’ai cependant trouvé un autre moyen, basé sur d’autres méthodes de substitution de paramètres, cette fois avec le remplacement de regex:
[[ "${var//*([[:digit:]])}" ]]; && echo "$var is not numeric" || echo "$var is numeric"
Il supprime tous les caractères: digit: class de $ var et vérifie s'il nous reste une chaîne vide, ce qui signifie que l'original était uniquement des nombres.
Ce que j'aime chez celui-ci, c'est son faible encombrement et sa flexibilité. Sous cette forme, il ne fonctionne que pour les entiers de base 10 non délimités, bien que vous puissiez sûrement utiliser la correspondance de modèle pour l'adapter à d'autres besoins.
Vous pouvez aussi utiliser "let" comme ceci:
[ ~]$ var=1
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=01
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=toto
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s not a number
[ ~]$
Mais je préfère utiliser l'opérateur "= ~" Bash 3+ comme certaines réponses de ce fil.
variable à vérifier
number=12345
ou number=-23234
ou number=23.167
ou number=-345.234
vérifier numérique ou non numérique
echo $number | grep -E '^-?[0-9]*\.?[0-9]*$' > /dev/null
décider d'autres actions en fonction du statut de sortie de ce qui précède
if [ $? -eq 0 ]; then echo "Numeric"; else echo "Non-Numeric"; fi
Suivi de Réponse de David W d'octobre 13, si vous utilisez expr
, cela pourrait être mieux
test_var=`expr $am_i_numeric \* 0` >/dev/null 2>&1
if [ "$test_var" = "" ]
then
......
Si numérique, multiplié par 1 vous donne la même valeur (y compris les nombres négatifs). Sinon, vous obtenez null
que vous pouvez tester
Pour attraper des nombres négatifs:
if [[ $1 == ?(-)+([0-9.]) ]]
then
echo number
else
echo not a number
fi
J'ai trouvé une version assez courte:
function isnum()
{
return `echo "$1" | awk -F"\n" '{print ($0 != $0+0)}'`
}
printf '%b' "-123\nABC" | tr '[:space:]' '_' | grep -q '^-\?[[:digit:]]\+$' && echo "Integer." || echo "NOT integer."
Supprimez le modèle correspondant -\?
dans grep si vous n'acceptez pas le nombre entier négatif.
Pour mon problème, je devais seulement m'assurer qu'un utilisateur n'entre pas du texte par accident, j'ai donc essayé de le garder simple et lisible
isNumber() {
(( $1 )) 2>/dev/null
}
Selon la page de manuel, cela correspond à peu près à ce que je veux.
Si la valeur de l'expression est non nulle, le statut de retour est 0
Pour éviter les messages d'erreur désagréables pour les chaînes qui "pourraient être des nombres", j'ignore la sortie d'erreur
$ (( 2s ))
bash: ((: 2s: value too great for base (error token is "2s")
J'aime la réponse d'Alberto Zaccagni.
if [ "$var" -eq "$var" ] 2>/dev/null; then
Conditions préalables importantes: - aucun sous-shell n'a été généré - aucun analyseur RE n'est appelé - la plupart des applications Shell n'utilisent pas de nombres réels
Mais si $var
est complexe (par exemple, un accès à un tableau associatif) et si le nombre sera un entier non négatif (la plupart des cas d'utilisation), cela est peut-être plus efficace?
if [ "$var" -ge 0 ] 2> /dev/null; then ..
Quick & Dirty: Je sais que ce n'est pas la manière la plus élégante, mais d'habitude, je viens d'ajouter un zéro et de tester le résultat. ainsi:
function isInteger {
[ $(($1+0)) != 0 ] && echo "$1 is a number" || echo "$1 is not a number"
}
x=1; isInteger $x
x="1"; isInteger $x
x="joe"; isInteger $x
x=0x16 ; isInteger $x
x=-32674; isInteger $x
$ (($ 1 + 0)) retournera 0 ou une bombe si $ 1 n'est PAS un entier. par exemple:
function zipIt { # quick Zip - unless the 1st parameter is a number
ERROR="not a valid number. "
if [ $(($1+0)) != 0 ] ; then # isInteger($1)
echo " backing up files changed in the last $1 days."
OUT="zipIt-$1-day.tgz"
find . -mtime -$1 -type f -print0 | xargs -0 tar cvzf $OUT
return 1
fi
showError $ERROR
}
NOTE: Je suppose que je n'ai jamais pensé à rechercher des types flottants ou mixtes qui rendraient le script explosif… dans mon cas, je ne voulais pas que cela aille plus loin Je vais jouer avec la solution de mrucci et les regex de Duffy - ils semblent les plus robustes dans le cadre bash ...
J'utilise ce qui suit (pour les entiers):
## ##### constants
##
## __TRUE - true (0)
## __FALSE - false (1)
##
typeset -r __TRUE=0
typeset -r __FALSE=1
## --------------------------------------
## isNumber
## check if a value is an integer
## usage: isNumber testValue
## returns: ${__TRUE} - testValue is a number else not
##
function isNumber {
typeset TESTVAR="$(echo "$1" | sed 's/[0-9]*//g' )"
[ "${TESTVAR}"x = ""x ] && return ${__TRUE} || return ${__FALSE}
}
isNumber $1
if [ $? -eq ${__TRUE} ] ; then
print "is a number"
fi
Si vous avez installé Perl, cette doublure est simple, lisible et extensible
Perl -se 'exit($n !~ /\d+/)' -- -n=a
Voici quelques tests
Perl -se 'exit($n !~ /\d+/)' -- -n=a; echo $?
1
Perl -se 'exit($n !~ /\d+/)' -- -n=2; echo $?
0
C'est assez explicite, mais voici plus d'informations
-e
permet l'évaluation-s
permet de passer des arguments après - dans ce cas, -n
!~
est l'opérateur de correspondance de regexp de négation, puisque 0 dans bash est un succès, nous voulons qu'il se termine correctement si l'argument -n
est un nombreVous voudrez envelopper ceci dans une fonction, ici une meilleure version qui peut aussi lire les floats
is_number() { Perl -se 'exit($n !~ /^\d+(\.\d+)?$/)' -- -n="$1"; }