Voici un exemple de script simple:
#!/usr/bin/env bash
if [ 1 == 1 ]; then
echo "Something"
fi
Quand je lance ça
sh ./test.sh
Je reçois:
./test.sh: 4: ./test.sh: Syntax error: "fi" unexpected (expecting "then")
Il ne semble pas reconnaître le "alors" que j'ai ici. Un indice quant à pourquoi? C'est Ubuntu pour Windows au cas où cette partie importerait.
L'exécution de scripts Shell en général n'est pas un problème, il semble simplement avoir du mal avec if/else.
Ici, nous avons deux problèmes. Tout d'abord, pendant que vous avez ligne Shebang appelant bash, vous exécutez le script en tant que sh script.sh
. La ligne Shebang spécifie déjà un interpréteur pour ce script. Donc, il suffit de rendre le script exécutable:
chmod a+x ./test.sh
Et puis lancez-le:
./test.sh
Sinon, lancez-le explicitement avec bash:
bash ./test.sh
Cela le fera fonctionner avec bash
au lieu de sh
qui est un shell plus limité et qui ne comprend pas ==
. Ce qui nous amène au deuxième problème et pourquoi cela échoue. Curieusement, vous voulez eq
ou =
, pas ==
. L'opérateur qui teste l'égalité numérique dans les scripts de shell POSIX (sh
est un shell compatible POSIX) est -eq
, tandis que celui qui teste string l'égalité est =
et ==
n'est pas une chose.
Donc, si vous voulez que votre script soit exécuté par sh
, remplacez-le par:
if [ 1 = 1 ]; then
echo "Something"
fi
Qui vérifie que la chaîne 1
est identique à la chaîne 1
, ou pour comparer numériquement, utilisez:
if [ 1 -eq 1 ]; then
echo "Something"
fi
De plus, vous avez un autre problème. Je ne peux reproduire l'erreur spécifique que vous obtenez dans dash
que si j'ajoute un \r
après le then
. C’est un problème classique lorsqu’on passe de Windows à Linux. Tandis que Linux utilise \n
comme caractère de fin de ligne, Windows termine ses lignes par \r\n
. Ce caractère \r
n'est pas visible par l'utilisateur, mais il existe et confond le script. Donc, vous pouvez l'enlever avec:
sed -i 's/\r//' ./test.sh
Et à l'avenir, utilisez un éditeur de texte approprié pour écrire vos scripts. Soit celui qui fonctionne dans le système WSL, ou celui qui peut au moins être configuré pour ne pas ajouter \r
aux extrémités de ses lignes.
Restons simples:
sh
n'est pas bash
sur Ubuntu (voir this pour référence).
[
est une commande, identique à la commande test
. Il ne supporte pas ==
pour la comparaison arithmétique. Utilisez -eq
à la place. Il s’agit de l’un des utilitaires spécifiés par normes POSIX , qui fonctionne donc à la fois dans bash
et dash
.
if [ 1 -eq 1 ];
then
echo "it works!"
fi
bash
a ((
qui s'appelle expansion arithmétique. Ceci supporte ==
. Cette fonctionnalité est apparemment empruntée à ksh
Shell.
$ var=25 bash -c 'if((var==5)); then echo Y;else echo "N";fi'
N
$ var=25 bash -c 'if((var==25)); then echo Y;else echo "N";fi'
Y
Malgré le fait que dash
ne prend pas en charge if (())
, dans l'un ou l'autre Shell $((
fonctionnera car il est mandaté par norme POSIX . En prenant uniquement les caractéristiques communes aux deux shells, nous pourrions faire quelque chose comme ceci tout en utilisant toujours ==
pour les comparaisons:
$ var=25 dash -c 'if [ $((var==25)) -eq 1 ];then echo Y; else echo N;fi'
Y
$ var=25 dash -c 'if [ $((var==5)) -eq 1 ];then echo Y; else echo N;fi'
N
Nous pourrions jeter complètement l'instruction if
et utiliser case
à la place (notez que le statut de retour est conforme à C, pas au comportement de Shell, c'est-à-dire que true vaut 1 et false vaut 0, et non l'inverse comme dans Shell) :
$ dash -c 'case $((1==1)) in 1) echo "equal";; 0) echo "not equal";;esac'
equal
$ dash -c 'case $((1==2)) in 1) echo "equal";; 0) echo "not equal";;esac'
not equal
ou nous pouvons devenir sournois avec (ab) en utilisant une expansion arithmétique:
$ var=25 dash -c '_0(){ false;}; _1(){ true;}; if "_$((var==25))" ; then echo Y; else echo N; fi'