web-dev-qa-db-fra.com

Comment tester si une variable est un nombre dans Bash?

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?

482
Flávio Amieiro

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]+)?$
648
Charles Duffy

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 (?*-*/*.*.*)

232
jilles

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):

  • Les nombres avec des points décimaux sont pas identifiés comme des "nombres" valides
  • Utiliser [[ ]] au lieu de [ ] sera toujours évalué à true
  • La plupart des shells non-Bash évalueront toujours cette expression avec true
  • Le comportement dans Bash est non documenté et peut donc changer sans avertissement
  • Si la valeur comprend des espaces après que le nombre (par exemple "1 a") produise une erreur, comme bash: [[: 1 a: syntax error in expression (error token is "a")
  • Si la valeur est identique à nom_var (par exemple, i = "i"), une erreur, telle que bash: [[: i: expression recursion level exceeded (error token is "i"), est générée.
154
Alberto Zaccagni

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";
33
mrucci

Personne n'a suggéré de bash correspondance étendue de motifs :

[[ $1 == ?(-)+([0-9]) ]] && echo "$1 is an integer"
28
glenn jackman

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.

27
pixelbeat

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]+$`
15
Sergio Abreu

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
12
triple_r

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
7
ultrasawblade

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.

7
Sammitch
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
6
user2683246
[[ $1 =~ ^-?[0-9]+$ ]] && echo "number"

N'oubliez pas - pour inclure des nombres négatifs!

6
D_I

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.

5
karttu

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.

5
overflowed

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
4
Andy

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
4
Aulo

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.

4
David W.

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; }
3
3ronco

Cela peut être réalisé en utilisant grep pour voir si la variable en question correspond à une expression régulière étendue.

Test entier 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.

Tester un 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.


Explication

  • La variable 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.
  • Le 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.".


Pour les flotteurs ou les doubles

Nous pouvons simplement changer l'expression régulière de '^[0-9]+$' à '^[0-9]*+\.?[0-8]+$' pour les floats ou les doubles.

Test float 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.

Test float 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 les négatifs

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]+$'.

2
Joseph Shih

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
1
Jerome

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.

1
ata

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.

1
Idriss Neumann
  • 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

1
Atanu

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 

1
Jon T

Pour attraper des nombres négatifs:

if [[ $1 == ?(-)+([0-9.]) ]]
    then
    echo number
else
    echo not a number
fi
1
user28490

J'ai trouvé une version assez courte:

function isnum()
{
    return `echo "$1" | awk -F"\n" '{print ($0 != $0+0)}'`
}
1
mary
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.

1
Ane Dijitak

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")
1
Hachi

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 ..
1
user3895088

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 ... 

1
WWWIZARDS

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
1
Marnix

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 nombre

Vous 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"; }
0
geckos