Comparer un entier en bash, opérateur unaire attendu

137

Le code suivant donne

[: -ge: opérateur unaire attendu

quand

i=0

if [ $i -ge 2 ]
then
    #some code
fi

Pourquoi?

Filip Ekberg
la source

Réponses:

295

Votre problème vient du fait qu'il $ia une valeur vide lorsque votre déclaration échoue. Citez toujours vos variables lorsque vous effectuez des comparaisons s'il y a la moindre chance que l'une d'elles soit vide, par exemple:

if [ "$i" -ge 2 ] ; then
  ...
fi

Ceci est dû à la façon dont le shell traite les variables. Supposons l'exemple d'origine,

if [ $i -ge 2 ] ; then ...

La première chose que le shell fait lors de l'exécution de cette ligne de code particulière est de substituer la valeur de $i, tout comme le ferait la fonction de recherche et de remplacement de votre éditeur préféré . Supposons donc que ce $isoit vide ou, encore plus illustratif, que ce $isoit un tas d'espaces! Le shell remplacera $icomme suit:

if [     -ge 2 ] ; then ...

Maintenant que les substitutions de variables sont effectuées, le shell procède à la comparaison et ... échoue car il ne peut rien voir d'intelligible à gauche de -gt. Cependant, citant $i:

if [ "$i" -ge 2 ] ; then ...

devient:

if [ "    " -ge 2 ] ; then ...

Le shell voit maintenant les guillemets doubles et sait que vous comparez en fait quatre espaces à 2 et ignorera le if.

Vous avez également la possibilité de spécifier une valeur par défaut pour $iif $iest vide, comme suit:

if [ "${i:-0}" -ge 2 ] ; then ...

Cela remplacera la valeur 0 au lieu de $iis $iest indéfini. Je maintiens toujours les guillemets car, encore une fois, s'il $iy a un tas de blancs, cela ne compte pas comme indéfini , il ne sera pas remplacé par 0 et vous rencontrerez à nouveau le problème.

Veuillez lire ceci lorsque vous en aurez le temps. Le shell est traité comme une boîte noire par beaucoup, mais il fonctionne avec très peu de règles très simples - une fois que vous savez quelles sont ces règles (l'une d'elles étant la façon dont les variables fonctionnent dans le shell, comme expliqué ci-dessus), le shell sera n’a plus de secrets pour vous.

vladr
la source
7
citant la variable augmentera une nouvelle erreur comme l' expression entière attendue
Néstor
@ Néstor faux , la citation d'une variable ne lèvera PAS une nouvelle erreur comme l' expression entière attendue si la variable est numérique; fournir une valeur variable non numérique, que ce soit cité ou non, se traduira par ladite erreur.
vladr
6

À en juger par le message d'erreur, la valeur de i était la chaîne vide lorsque vous l'avez exécutée, et non 0.

starblue
la source
6

Je dois ajouter mes 5 cents. Je vois que tout le monde utilise [ou [[, mais il convient de mentionner qu'ils ne font pas partie de la syntaxe if.

Pour les comparaisons arithmétiques, utilisez ((...))plutôt.

((...)) est une commande arithmétique, qui renvoie un état de sortie de 0 si l'expression est différente de zéro, ou 1 si l'expression est égale à zéro. Également utilisé comme synonyme de «let», si des effets secondaires (affectations) sont nécessaires.

Voir: ArithmeticExpression

Roman Newaza
la source
2

Votre morceau de script fonctionne très bien. Etes-vous sûr de n'attribuer rien d'autre avant le if à "i"?

Une erreur courante est également de ne pas laisser d'espace après et avant les crochets.

Fernando Miguélez
la source