ce sujet est une digression de : ce script qui n'en fait qu'à sa tête où la question de l'existence d'une variable a été soulevée.
:
...Envoyé par jack-ftEnvoyé par NBaH
ce sujet est une digression de : ce script qui n'en fait qu'à sa tête où la question de l'existence d'une variable a été soulevée.
:
...Envoyé par jack-ftEnvoyé par NBaH
Envoyé par jack-ftGénéralement pas indispensable, effectivement.Envoyé par N_BaH
Mais je n'aime pas laisser à l'implémentation (ou aux spécifications) du langage la responsabilité d'initialiser les variables.
Un débutant ne sait pas toujours quelle est la valeur par défaut d'une variable qui n'est pas explicitement initialisée.
Du coup, lorsqu'un débutant lit du code (non pondu par lui) où une variable est explicitement initialisée (même à ce qui serait sa valeur par défaut si elle n'était pas initialisée), je trouve que c'est plus clair pour lui.
Sans compter les prudents (dont j'ai pu faire partie...):
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 % cat ./test.sh #!/bin/bash if test "$a" = ""; then echo "a vide (ou non initialisée)"; else echo "a pas vide"; fi set -u if test "$a" = ""; then echo "a vide (ou non initialisée)"; else echo "a pas vide"; fi % ./test.sh a vide (ou non initialisée) ./test.sh: line 4: a: unbound variable
Bien fait ! T'avais qu'à initialiser ta variable !
Attention! Le set -u n'est pas nécessairement du masochisme volontaire !
J'ai eu vu des environnements où les scripts étaient lancés avec des trucs comme bash -u ou où les .profile imposaient le set -u...
Déjà en shell la question ne se pose même pas: une variable qui n'est pas initialisée n'existe tout simplement pas (et donc elle n'a même pas de valeur par défaut). C'est d'ailleurs pour ça qu'on écrit toujours des guillemets quand on compare une variable avec une chaine (ex [ "$str" = "toto" ]) => au cas où $str n'existerait pas.
Et pour les langages qui acceptent des variables sans initialisation (ex le C) alors ça n'a pas vraiment d'importance non plus grace au principe de précaution qui est de ne jamais lire une variable qui n'a pas été préalablement remplie. Si on applique ce principe, on n'aura aucun souci quelle que soit la politique d'initialisation par défaut du langage (et on n'a même pas besoin de la connaitre)
Ca rassure en effet de savoir qu'une variable sera toujours créée avant d'être utilisée (en plus ça rejoint le principe de précaution dont j'ai parlé)
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
Bonjour
M'sieur ! M'sieur ! pourquoi vous dites "bien fait" ? Regardez mon écran. Tout marche bien.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 $ a=7 ./test.sh a pas vide a pas videJe me crispe. Une variable peut être testée sans être initialisée. Donc elle existe.une variable qui n'est pas initialisée n'existe tout simplement pas
Pas au cas où elle n'existerait pas, mais au cas où elle serait vide. Elle peut être initialisée et être devenue vide. Cas inverse du précédent.au cas où $str n'existerait pas.
Mais non ! C'est faux ! J'ai des scripts avec des modes cachés que j'active avec la technique montrée ci-dessus. Et je teste des variables jamais créées par défaut. Et le comportement du script change en fonction de variables inconnues auxquelles je fixe des valeurs connues de moi seul.Ca rassure en effet de savoir qu'une variable sera toujours créée avant d'être utilisée
Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.
Non. Tester (de même qu'afficher) une variable qui n'existe pas fonctionne (pour peu que le test soit correctement écrit)... mais ne la fait pas exister pour autant (d'ailleurs si cela la faisait exister je ne vois pas à quoi servirait l'option set -u).
D'ailleurs le shell fait bien la différence entre "ne pas exister/exister à vide/exister à non vide" car il y a ${var-texte} (qui renvoie "$var" si celle-ci existe ; et sinon renvoie le texte "texte") et ${var:-texte} (qui renvoie "$var" si celle-ci existe et qu'elle est non vide ; et sinon renvoie le texte "texte")
Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 $ maVariable=123 $ set |grep maVariable maVariable=123 # Là elle existe $ echo "${maVariable:-toto}" 123 $ unset maVariable $ set |grep maVariable $ # Là elle n'existe plus $ echo "${maVariable:-toto}" toto $ [ -z "$mavariable" ] && echo "le test se fait bien" le test se fait bien $ set |grep maVariable $ # Elle n'existe toujours pas
Non, je dis bien "si la variable n'existe pas". On peut tester une variable inexistante, encore une fois si on veille bien à positionner des éléments permettant de ne pas avoir de test bancal
Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 $ maVariable=toto $ set |grep maVariable maVariable=toto $ test $maVariable = toto && echo "oui toto" || echo "non toto" oui toto $ unset maVariable $ test $maVariable = toto && echo "oui toto" || echo "non toto" bash: test: = : opérateur unaire attendu non toto $ test _$maVariable = _toto && echo "oui toto" || echo "non toto" non toto $ test "$maVariable" = "toto" && echo "oui toto" || echo "non toto" non toto $ set |grep maVariable $
Et ces précautions de mettre des éléments en plus de chaque côté de l'égalité (l'underscore, les guillemets) s'appliquent aussi dans le cas que tu cites d'une variable existante mais vide (qui est un cas assez ressemblant au premier pour qu'on s'autorise à ne pas faire de distinction lors des tests)
Tu n'as pas compris ma phrase. Je disais "ça rassure de mettre set -u car on sait que ainsi, on l'on ne pourra pas utiliser (afficher, tester) des variables inexistantes (c'est une barrière facultative que l'on s'impose volontairement)".
Mais bien évidemment, si tu utilises des variables qui seront remplies (créées) uniquement dans certains cas particuliers (style "si la variable est remplie je fais telle action en plus") tu ne peux plus mettre set -u car au premier test de ta variable, si celle-ci n'existe pas le script plantera. Mais t'es pas obligé de mettre set -u si tu ne le veux pas. Cette phrase était destinée à jack-ft pour expliquer pourquoi certains admins imposent un set -u dans le .profile => pour se protéger contre les erreurs style "j'utilise mavariable alors qu'elle se nomme en réalité maVariable" (mais dans ce cas j'y rajouterais aussi set -e pour planter le script si erreur).
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
je voudrais que nous puissions formaliser(?) tout ça. sereinement;
les états d'une variable
avant son utilisation, il existe plusieurs états possibles pour une variable :
- "non état" : elle n'existe pas (pas déclarée, ou supprimée unset v)
- déclarée (declare v)
- assignée
- sans valeur (v='')
- avec une valeur (v='V')
plusieurs tests sont possibles :
1.et 2.3a.
Code : Sélectionner tout - Visualiser dans une fenêtre à part declare -p v &>/dev/null3b.
Code : Sélectionner tout - Visualiser dans une fenêtre à part test -v v
Code : Sélectionner tout - Visualiser dans une fenêtre à part test -n "$v"
Tout à fait d'accord avec les états d'âme d'une variable...
mais peut-on distinguer les deux premiers cas (unset et déclarée), c'est-à-dire avoir l'information qu'une variable est déclarée ?
Comme je ne connaissais pas test -v, j'avais produit il y a quelque temps le tableau suivant (auquel je me réfère en cas de doute (et de flemme)):
Code x : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 +=======================+=========+=========+=========+ | Instruction | unset V | V='' | V='X' | +-----------------------+---------+---------+---------+ | State of V | unset | empty | set | +=======================+=========+=========+=========+ | "${V-D}" | 'D' | '' | 'X' | +-----------------------+---------+---------+---------+ | "${V:-D}" | 'D' | 'D' | 'X' | +-----------------------+---------+---------+---------+ | "${V+D}" | '' | 'D' | 'D' | +-----------------------+---------+---------+---------+ | "${V:+D}" | '' | '' | 'D' | +=======================+=========+=========+=========+ | test -z "${V+D}" | true | F | F | unset +-----------------------+---------+---------+---------+ | test -z "${V-D}" | F | true | F | empty (set to empty) +-----------------------+---------+---------+---------+ | test -n "${V:+D}" | F | F | true | set (but not empty) +=======================+=========+=========+=========+ | test -n "${V+D}" | F | true | true | not unset (set or empty) +-----------------------+---------+---------+---------+ | test -n "${V-D}" | true | F | true | not empty (unset or set) +-----------------------+---------+---------+---------+ | test -z "${V:+D}" | true | true | F | not set (unset or empty) +=======================+=========+=========+=========+ | "${V-A}${V-B}" = "AB" | true | F | F | unset +=======================+=========+=========+=========+
Et ça marche même avec le set -u:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 % cat test.sh #!/bin/bash if test "$a" = ""; then echo "a vide (ou non initialisée)"; else echo "a pas vide"; fi set -u if test -z "${a+D}"; then echo "Attention: 'a' n'est pas initialisée"; fi if test "$a" = ""; then echo "a vide (ou non initialisée)"; else echo "a pas vide"; fi
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 % ./test.sh a vide (ou non initialisée) Attention: 'a' n'est pas initialisée ./test.sh: line 9: a: unbound variable
c'est ce que je montre avec &>/dev/null declare -p, cette commande à qui on fournit une variable déclarée retourne 0 (vrai).peut-on distinguer les deux premiers cas (unset et déclarée), c'est-à-dire avoir l'information qu'une variable est déclarée ?
hmmm
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 $ unset foo $ test -v foo $ echo $? 1 $ foo='' $ test -v foo $ echo $? 0 $ foo='bar' $ test -v foo $ echo $? 0
Cordialement.
donc pas le cas de 3a mais 3 tout court
Cordialement.
test -v teste si une variable est assignée, pas si cette assignation a une valeur.
c'est ce que j'ai dit : une valeur null ne vaut pas pas une valeur text/int
tout n'est limpide pour moi (je suis un utilisateur) ; pour faire vraiment bien il faudrait savoir entrer dans les entrailles du shell.
il paraît que c'est tout con : ce serait une boucle qui attend des instructions...
Si, le cas 3 (variable existante) se subdivise en 3a (variable existante vide) et 3b (variable existante non vide) parce que le shell, comme je l'ai dit, fait lui-même cette distinction. Déjà avec test -n/test -z mais aussi avec ${var-toto} qui se contente d'agir selon l'existence de $var ; versus ${var:-toto} qui, lui, checke l'existence $var mais aussi qu'elle soit non vide.
Moi non plus je ne connaissais pas test -v mais en plus j'ai remarqué que ce test doit s'appliquer à la variable elle-même et non pas à son contenu (pas de "$" devant le nom de la variable).
Pour l'instant j'essaye de réfléchir s'il peut me servir (c'est à dire dans quelle configuration il peut remplacer un test -z)...
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
test -v est un "bashisme".
je voudrais aussi qu'on n'extrapole pas sur le développement potentiel de variable : on pourrait aussi lui faire dire leur contraire de ce qu'on veut tester.
une variable
n'existe pas
existe
a une valeur
...
le B-A-BA
Je reste sur ma position, une variable vide est un element de comme un autre d'une variable avec une valeur.
Pour moi, ce qui fait loi , c'est la table de vérité et donc le test -v répond vrai pour les 2 cas (qui n'en est qu'un dans la réalité).
Là, j'ai l'impression que l'on mélange des pommes et des bananes
Cordialement.
Une variable inexistante ou vide ne peut pas retourner de valeur, c'est la même chose contrairement à une variable positionnée. Si on fait une comparaison devant tester si la variable est égale à 1 ou 2 que celle-ci soit existante ou vide la variable ne sera ni égal à 1 ni à 2. Si par contre mon test doit vérifier si ma variable est supérieure ou égale à 1, c’est pas forcément la même chose. Il faut connaitre le comportement du système utilisé, dans notre cas Bash et faire une algorithmie cohérente par rapport à celui-ci.
Ne maitrisant pas forcément Bash, j'opterais pour positionner une variable à 0 (ou à "" pour une chaine), ce qu'un utilisateur avancé pourra trouver inutile.
Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
Mon article sur le P2V, mon article sur le cloud
Consultez nos FAQ : Windows, Linux, Virtualisation
"vide" (NULL en C, None en Python, null dans les bases de données) peut-il être considé comme une valeur?
Les bases de données, par exemple, disent clairement que non. Une colonne qui possède une contrainte d'unicité (interdit d'avoir plusieurs fois la même valeur dans cette colonne pour l'ensemble des lignes de la table) accepte que cette colonne soit null pour plusieurs lignes. La notion de "null" (en bdd) n'est donc pas une valeur au sens propre du terme. A tel point que dans les requêtes avec jointure, il faut préciser l'action si une ligne de la table A n'a pas de correspondance (pas de valeur) en table B via inner join/outer join
De façon plus philosophique, imaginons une table de personnes avec nom, prénom, ville de naissance (null possible). On veut toutes les personne nées à Lyon. Que faire si l'info "ville" n'a pas de valeur pour telle personne? Doit-elle apparaitre aussi au résultat (peut-être qu'elle est quand-même née à Lyon)? Admettons mais si on cherche les personnes nées à Paris avec la même requête, cette même personne sortira aussi au résultat.
Non, de mon point de vue la notion "pas de valeur" n'a pas la même signification que la notion "telle ou telle valeur".
C'est le cas justement avec ton test -v qui demande en réalité "est-ce que ceci est une variable" sans se préoccuper de sa valeur. Tu compares pommes et bananes pour dire "oui ce sont des fruits". Peut-on dire pour autant que c'est la même chose?
Tu as pris un exemple particulier de test mais il y a plein de contre-exemples possibles. Que fais-tu de echo ${var-toto} vs echo ${var:-toto} qui ne sortent pas la même chose dans les 2 cas? Que fais-tu de test $var = Luke_je_suis_ton_pere qui réussira dans un cas et plantera lamentablement dans l'autre?? Que fais-tu de set -u qui fera en sorte que le shell te renvoie une erreur à chaque fois que tu feras echo $var jusqu'à ce que tu écrives enfin une instruction var=valeur???
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
Je persiste, faire des sous ensemble 3a et 3b pour un ensemble 3 n'est pas claire et contre intuitif vis à vis de la table de vérité du test -v.
Ce test est une notion meta vis à vis de l'ensemble, il ne teste pas une propriété d'un objet, il teste l'existance de celui-ci.
Cordialement.
test -v indique si une variable est assignée (3). Ce test ne dit pas si la variable a une valeur.
test -n indique si une variable a une valeur (3b).
je ne sais pas comment le présenter : "a une valeur" est un sous-ensemble "est assignée".
ce ne sont pas des éléments "parallèles" comme le suggère la dichotomie 3a 3b.
serait-ce :
- "non état" : elle n'existe pas (pas déclarée, ou supprimée (unset v))
- déclarée (declare v)
- assignée (v='', ou v='Val')
- avec une valeur (v='Val')
et donc :
3.3a.
Code : Sélectionner tout - Visualiser dans une fenêtre à part test -v v
Code : Sélectionner tout - Visualiser dans une fenêtre à part test -n "$v"
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager