si, elif, else, les problèmes de déclaration dans Bash

359

Je n'arrive pas à comprendre quel est le problème avec la ifdéclaration suivante en ce qui concerne laelif et then. Gardez à l'esprit que le projet printfest toujours en cours de développement, mais je n'ai pas encore pu le tester dans la déclaration, il est donc très probablement faux.

L'erreur que je reçois est:

./timezone_string.sh: line 14: syntax error near unexpected token `then'
./timezone_string.sh: line 14: `then'

Et la déclaration est comme ça.

if [ "$seconds" -eq 0 ];then
   $timezone_string="Z"
elif[ "$seconds" -gt 0 ]
then
   $timezone_string=`printf "%02d:%02d" $seconds/3600 ($seconds/60)%60`
else
   echo "Unknown parameter"
fi
StuStirling
la source
7
Je me demande pourquoi nous avons besoin de la thendéclaration dans ifet elifmais pas dans else, et aussi en général.
@ w17t, car nous devons séparer la condition de la séquence.
Sasha
3
@codeforester Je ne vois pas beaucoup de logique sur le fait de marquer une question à 500K vues en double à une qui n'a que 5K
fedorqui 'SO stop harming'
L'utilisation de certains outils de mise en forme automatique du code peut vous aider en ajoutant / supprimant automatiquement des espaces autour des crochets. Vous pouvez rechercher des plugins pour votre éditeur.
Nj Subedi

Réponses:

453

Il manque un espace entre elifet [:

elif[ "$seconds" -gt 0 ]

devrait être

elif [ "$seconds" -gt 0 ]

Comme je vois que cette question reçoit beaucoup de vues, il est important d'indiquer que la syntaxe à suivre est:

if [ conditions ]
# ^ ^          ^

ce qui signifie que des espaces sont nécessaires autour des crochets . Sinon, cela ne fonctionnera pas. C'est parce que [lui - même est une commande.

La raison pour laquelle vous ne voyez pas quelque chose comme elif[: command not found(ou similaire) est que , après avoir vu ifet then, la coquille est soit à la recherche elif, elseou fi. Cependant, il en trouve un autre then(après le formatage incorrect elif[). Ce n'est qu'après avoir analysé l'instruction qu'elle sera exécutée (et un message d'erreur comme celui- elif[: command not foundci sera émis).

fedorqui 'SO arrête de nuire'
la source
33
La raison pour laquelle les crochets ont besoin d'espaces est qu'ils ne sont que des raccourcis pour des programmes réels (au moins le premier crochet, le second n'est que du sucre syntaxique si je comprends bien). Pour le comprendre, consultez la page de manuel réelle du support gauche:$ man [
Michael Johansen
3
Ce message n'est-il pas censé être fermé en tant que faute de frappe?
zx8754
3
@ zx8754 aurait pu l'être, mais ce n'est pas devenu un moyen canonique de corriger cette erreur, qui semble assez utile (vues 360K et comptage).
fedorqui 'SO arrête de nuire'
3
Certains de mes collègues ne comprennent pas le concept d'un "espace" ou d'un "style de codage", ce n'est donc peut-être pas une faute de frappe.
juzzlin
3
[est une sorte d'alias pour la commande de test. C'est pourquoi le caractère vide est requis. if test "$seconds" -eq 0; then ... fiest équivalent à if [ "$seconds" -eq 0 ];then ... fi ]. @LeiYang man testest ce que vous cherchez réellement
Melicerte
304

Vous avez des problèmes de syntaxe avec votre script. Voici une version fixe:

#!/bin/bash

if [ "$seconds" -eq 0 ]; then
   timezone_string="Z"
elif [ "$seconds" -gt 0 ]; then
   timezone_string=$(printf "%02d:%02d" $((seconds/3600)) $(((seconds / 60) % 60)))
else
   echo "Unknown parameter"
fi
anubhava
la source
76
Curieusement, c'était la seule construction complète et simple bash "si-alors-autre" que j'ai facilement trouvée sur stackexchange ... merci.
Wildcard
1
l'indentation est facultative. l'interprète peut (et devrait) être #!/bin/sh.
3
@ Chinggis6 Total non-sens, l'interprète pourrait être #!/bin/shmais n'a pas à le faire.
Camusensei
4
@Camusensei ce n'est pas un non-sens total car il shpeut être utilisé à la place pour une meilleure compatibilité (toutes les distributions * nix n'ont pas bash comme shell par défaut (certains ont ksh ou ash mais la plupart dépendent du standard shpour fonctionner). ou les fonctionnalités avancées ne sont pas utilisées dans le script, alors 'sh' doit être utilisé comme interprète (une raison de plus pour cela) car il peut gérer le script lui-même.
6
@ Chinggis6 Vrai, mauvais choix de mots de mon côté.
Camusensei
25

[est une commande (ou intégrée dans certains shells). Il doit être séparé par des espaces de l'instruction précédente:

elif [
choroba
la source
3
Il est remplacé par une fonction intégrée dans bash, mais votre message est toujours correct. utiliser type -a [pour voir cela.
Camusensei
C'est aussi un binaire qui m'a toujours paru étrange.
mr.zog
4

Je vous recommanderais de jeter un œil aux bases du conditionnement en bash.

Le symbole "[" est une commande et doit être précédé d'un espace. Si vous ne donnez pas d'espace après votre elif, le système interprète elif [ comme une commande particulière qui n'est certainement pas ce que vous voudriez en ce moment.

Usage:

elif(A COMPULSORY WHITESPACE WITHOUT PARENTHESIS)[(A WHITE SPACE WITHOUT PARENTHESIS)conditions(A WHITESPACE WITHOUT PARENTHESIS)]

En bref, modifiez votre segment de code pour:

elif [ "$seconds" -gt 0 ]

Vous iriez bien sans erreurs de compilation. Votre segment de code final devrait ressembler à ceci:

#!/bin/sh    
if [ "$seconds" -eq 0 ];then
       $timezone_string="Z"
    elif [ "$seconds" -gt 0 ]
    then
       $timezone_string=`printf "%02d:%02d" $seconds/3600 ($seconds/60)%60`
    else
       echo "Unknown parameter"
    fi
M. Weirdo
la source
2

L'espace manquant entre elifet [reste votre programme est correct. vous devez le corriger et le vérifier. voici le programme fixe:

#!/bin/bash

if [ "$seconds" -eq 0 ]; then
   timezone_string="Z"
elif [ "$seconds" -gt 0 ]; then
   timezone_string=$(printf "%02d:%02d" $((seconds/3600)) $(((seconds / 60) % 60)))
else
   echo "Unknown parameter"
fi

lien utile lié à cette instruction bash if else

John Walsh
la source