Problème de boucle avec "until"

L’auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour,

Je ne comprends pas l’erreur affichée par la deuxième boucle dans le programme suivant :

#!/bin/bash

echo "Merci de saisir le premier mdp : "

while [ -z $v ] || [ $v != "pass1" ]; do
    read v
    echo "Mdp incorrect !"
done

echo "Très bien, maintenant le 2e : "

until [ -n $v2 ] && [ $v2 = "pass" ]; do
    read v2
    echo "Mdp incorrect !"
done

echo "C'est bon, vous êtes authentifié !"
screenshot.PNG
screenshot.PNG

Pour créer la condition de la boucle until, j’ai simplement inversé logiquement la condition de la première boucle. Pourtant, il semble qu’il ne reconnaît pas la syntaxe, où me suis-je planté ?

J’en profite pour signaler que les mots-clefs until et read ne sont pas surlignés dans le code, peut-être un bug du Zmarkdown ?

+0 -0

Salut,

Le souci est au niveau de [ -n $v2 ]. En fait, si tu souhaites tester si une variable est définie avec l’option -n de la commande test(1) tu dois entourer la variable de guillemets double. Si tu ne le fais pas, lorsque la variable est vide, c’est comme si tu écrivais test -n, ce qui est invalide (il manque un argument). ;)

Édité par Taurre

#JeSuisArius

+2 -0

Cette réponse a aidé l’auteur du sujet

La syntaxe de (ba)sh est une horreur absolue. Il est recommandée de "protéger" les variables (l 12) :

#!/bin/bash

echo "Merci de saisir le premier mdp : "

while [ -z $v ] || [ $v != "pass1" ]; do
    read v
    echo "Mdp incorrect !"
done

echo "Très bien, maintenant le 2e : "

until [ -n $v2 ] && [ "$v2" = "pass" ]; do
    read v2
    echo "Mdp incorrect !"
done

echo "C'est bon, vous êtes authentifié !"

Alternative : passer par les doubles crochets :

until [ -n $v2 ] && [[ $v2 = "pass" ]]; do

Édit : La solution de @Taurre marche aussi. Il suffit donc de protéger l’un des deux v2, et c’est bon… Gneuh.

Édité par Gabbro

Il y a bien des façons de passer à l’acte. Se taire en est une. Attribué à Jean-Bertrand Pontalis

+0 -0

Édit : La solution de @Taurre marche aussi. Il suffit donc de protéger l’un des deux v2, et c’est bon… Gneuh.

Gabbro

Dans tous les cas, le premier, a minmima (si -n est utilisé). ;)

Édit :

La syntaxe de (ba)sh est une horreur absolue.

Gabbro

Ben quoi, c’beau, non ? :p

Édité par Taurre

#JeSuisArius

+0 -0
Auteur du sujet

Merci en effet, je vais systématiquement entourer mes variables par des "" lorsque je sens que ça peut planter à cause de ça.

Dans tous les cas, le premier, a minmima (si -n est utilisé).

Entourer seulement le 2e fonctionne aussi chez moi.
Entourer les deux, c’est encore mieux je suppose ? :)

+0 -0

Entourer seulement le 2e fonctionne aussi chez moi.
Entourer les deux, c’est encore mieux je suppose ? :)

Green

Ah ! Oui, en effet, au temps pour moi.
Visiblement mon explication est erronée : s’il n’y a pas d’argument fourni pour l’option -n alors le test est « vrai », mais c’est syntaxiquement valide. Le souci était donc bien, comme @Gabbro le suggérait, du côté du second test.

Édité par Taurre

#JeSuisArius

+0 -0
Auteur du sujet

Ah je crois avoir compris pourquoi ça plante !
En fait il substitue littéralement $v2 avec sa valeur, donc du vide, d’où l’erreur de syntaxe.

En plus @entwanne me l’avait fait remarquer sur mon dernier sujet :honte:

Résolu, pour de bon ! :)

+0 -0
Auteur du sujet

Salut,

Le souci est au niveau de [ -n $v2 ]. En fait, si tu souhaites tester si une variable est définie avec l’option -n de la commande test(1) tu dois entourer la variable de guillemets double. Si tu ne le fais pas, lorsque la variable est vide, c’est comme si tu écrivais test -n, ce qui est invalide (il manque un argument). ;)

Taurre

Re, cette histoire de commande test m’a un peu troublé mais je pense que test est en fait un programme exécutable (une commande donc) :

#!/bin/bash

read v

if test "$v" = "pass"; then
    echo "OK"
fi

Du coup, puis-je affirmer que la notation [ a b c … ] est strictement équivalente à test a b c … où a, b et c sont des paramètres ?

+0 -0

Cette réponse a aidé l’auteur du sujet

Re, cette histoire de commande test m’a un peu troublé mais je pense que test est en fait un programme exécutable (une commande donc) :

Green

C’est le cas, oui et [ également, en fait. ^^

$ which [
/bin/[

Ce sont d’ailleurs normalement les deux mêmes commandes (c’est le cas chez moi, sous OpenBSD).

$ sha1 /bin/[ /bin/test
SHA1 (/bin/[) = 24e716c8fbf9de5e1edeb037312eb906d0b72d6c
SHA1 (/bin/test) = 24e716c8fbf9de5e1edeb037312eb906d0b72d6c

Du coup, puis-je affirmer que la notation [ a b c … ] est strictement équivalente à test a b c … où a, b et c sont des paramètres ?

Green

Yep. :)
J’utilise d’ailleurs en général test(1) de mon côté car je trouve cela plus clair. ;)

Édit : certains shell implémentent [ en interne et n’utilise donc pas la commande [. C’est donc possible que /bin/[ ne soit pas présent sur ta distribution.

Édité par Taurre

#JeSuisArius

+0 -0

Ce sont d’ailleurs normalement les deux mêmes commandes (c’est le cas chez moi, sous OpenBSD).

$ sha1 /bin/[ /bin/test
SHA1 (/bin/[) = 24e716c8fbf9de5e1edeb037312eb906d0b72d6c
SHA1 (/bin/test) = 24e716c8fbf9de5e1edeb037312eb906d0b72d6c

Pas chez moi (Linux OpenSuse) :

$ sha1sum /usr/bin/\[ /usr/bin/test 
07f193de0831a5895f387108e9f097540a4503c5  /usr/bin/[
bc53a8c2fc86d2eb6d3755ce20098058d4d210ef  /usr/bin/test

Mais man /usr/bin/[ me renvoie sur le man de test, donc il doit y avoir une petite différence, mais c’est bien sensé faire la même chose.

Édité par Gabbro

Il y a bien des façons de passer à l’acte. Se taire en est une. Attribué à Jean-Bertrand Pontalis

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte