script bash [x $ 1 = x]


21

Je lis le script bash, je ne comprends pas ce qui s'y passe.

#!/bin/sh
[ x$1 = x ] 

Que se passe-t-il sur la deuxième ligne et que [ x$1 = x ] signifie-t-il?

Réponses:


27

Cela vérifie qu'il $1est vide, bien qu'il doive être cité (identique à [ -z "$1" ]). Certains très vieux shells ne géraient pas correctement les chaînes vides, donc les rédacteurs de scripts portables ont adopté ce style de vérification. Cela n'a pas été nécessaire depuis des décennies, mais les gens le font toujours de cette façon parce que les gens le font toujours de cette façon.


Ouais, tu ne devrais plus le faire comme ça et adopter un style plus moderne. Sauf si vous travaillez sur un PDP11.
MacLemon

4
Il ne s'agit pas autant de chaînes vides. [ x$1 = x ]est toujours incorrect, mais [ "x$1" = x ]serait pour les shells qui ont un problème où $1est !ou (ou -n.... [ "" = "$1" ]et case $1 in "")serait également OK cependant.
Stéphane Chazelas

2
@MacLemon, pas besoin de remonter aussi loin. [ -z "$1" ]et [ "$1" = "" ]ne fonctionnent toujours pas avec / bin / sh de Solaris 10, le premier avec dash-0.5.4.
Stéphane Chazelas

1
+1 supplémentaire pour la dernière phrase!
glenn jackman

1
@glennjackman, cette dernière phrase est incorrecte. Solaris 10 est toujours la version la plus largement déployée de Solaris et [ "$1" = "" ]ne fonctionne toujours pas avec son /bin/sh(bien que vous souhaitiez l'utiliser /usr/xpg4/bin/shlà-bas, non /bin/sh). un tiret a été fixé à cet égard en janvier 2009.
Stéphane Chazelas

8

Les crochets indiquent un test , donc [ x$1 = x]sans ifou quelque chose de similaire n'a pas de sens, bien que syntaxiquement correct.

Il est censé évaluer vrai si se x$1développe en xet faux sinon, mais comme il n'est pas cité, si $1est (par exemple) "hey x", le shell verra x = x, donc cette construction n'est toujours pas sûre.

Le but de la x = xvérification est de déterminer si une variable est vide. Une façon plus courante de le faire serait d'utiliser simplement des guillemets:

if [ "$1" = "" ]; then

Les opérateurs de test Bash -zet -npeuvent également être utilisés, mais ils sont moins portables pour d'autres types de coques. 1

La raison des guillemets, ou du x$1, est que le côté gauche ne se développe pas à rien, ce qui serait une erreur syntaxique:

if [  = x ]  # No good!
if [ "" =  "" ] # Okay.
if [ x = x ] # Also okay.

1. En fait, il testpeut s'agir d'un utilitaire autonome, mais la plupart des shells l'implémentent en tant que fonction intégrée; vérifier la différence entre which testet type test. Sur GNU / Linux man test, il fait référence à la version intégrée, mais si vous appelez (par exemple) /usr/bin/test, cet utilitaire semble implémenter les fonctionnalités documentées dans la page de manuel, y compris -zet -n.


1
[ x$1 = x ]sera également évalué à true si $1est par exemple " -o x". Essayez sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]est faux et n'a pas de sens.
Stéphane Chazelas

@ StéphaneChazelas Merci SC - édité (2e para).
goldilocks

vous n'avez pas besoin ifd'utiliser test, vous pouvez l'utiliser avant &&, ||ou après whileou examiner le résultat en utilisant$?
Jasen

8
[ x$1 = x ]

Cela n'a de sens que zsh. Cela compare la concaténation de xavec le premier argument du script à x. La [commande retourne donc vrai si $1est vide ou non fourni.

[ $1 = "" ]

Ne fonctionnerait pas parce que, zshquand une variable vide n'est pas cité dans des contextes de la liste, il se dilate à aucun argument du tout au lieu d'un argument vide, donc si $1était unset ou vide, la [commande ne recevrait comme arguments [, =la chaîne vide et ]dont il ne pouvait pas donner de sens. [ -z "$1" ]ou [ "$1" = "" ]serait OK mais comme dans les shells POSIX.

Dans les shells Bourne-like / POSIX, cela [ x$1 = x ]n'a pas de sens. C'est l'opérateur split + glob appliqué d'une manière ou d'une autre à la concaténation de xet au premier argument du script en espérant que le résultat et =et x, et ]constituent une expression de test valide pour la [commande.

Par exemple, si le script a été adopté un " = x -o x ="argument [recevrait ces arguments: [, x, =, x, -o, x, =, x, ], qui [comprendrait que la comparaison xavec xet xavec xet retour vrai.

Si $1c'était le cas "* *", le shell transmettrait à la [commande la liste des fichiers du répertoire courant dont le nom commence par x(l'expansion globale de x*), puis la liste des fichiers non cachés (expansion *) ... qui [est peu susceptible de pouvoir pour donner un sens à. Le seul cas où cela ferait quoi que ce soit de sensé est s'il $1ne contient pas de caractère générique ou de caractères vides.

Maintenant, ce que vous trouvez parfois, c'est du code comme:

[ "x$1" = x ]

Il est utilisé pour tester s'il $1est vide ou non défini.

La façon normale de tester une variable vide ou non définie est la suivante:

[ -z "$1" ]

Mais cela échoue pour certaines valeurs de $1like =dans certaines [implémentations (non-POSIX) comme celle intégrée dans le shell Bourne comme /bin/shsur Solaris 10 et avant ou certaines anciennes versions de dash(jusqu'à 0.5.4) ou shcertains BSD.

En effet , [voit [, -z, =, ]et se plaint de manquer des arguments à l' =opérateur binaire au lieu de comprendre que l' -zopérateur unaire appliqué à la =chaîne.

De même, [ "$1" = "" ]échoue pour certaines implémentations de [si $1est !ou (.

Dans ces shell / [implémentations:

[ "x$1" = x ]

est toujours un test valide quelle que soit la valeur de $1, sont donc:

[ "" = "$1" ]

et:

[ -z "${1:+x}" ]

et

case $1 in "") ...; esac

Bien sûr, si vous voulez vérifier qu'aucun argument n'est fourni, vous feriez:

[ "$#" -eq 0 ]

Autrement dit, vous vérifiez le nombre d'arguments transmis au script.

Notez que de nos jours, [ -z "$var" ]est clairement spécifié par POSIX et ne peut pas échouer dans conforme à l ' [implémentations (et bashl » [est et a été pendant des décennies). Vous devriez donc pouvoir vous y fier dans POSIX sh ou dans des bashscripts.


0

x$1concatène deux chaînes xet $1si $ 1 est vide, x $ 1 est égal à x, et [x $ 1 = x] sera vrai en conséquence. x = yest utilisé pour comparer la chaîne en sh


2
Non x$1n'est pas cité, donc le fractionnement et la globalisation sont effectués sur ceux-ci.
Stéphane Chazelas

0

[ x$1 = x ]est vrai si $1est non défini / null / vide ou non.
Essayez-vous avec:
TEST= ;[ x$TEST = x] && echo "TEST is unset"
et
TEST=lolz ;[ x$TEST = x ] && echo "TEST is unset"


1
[ x$1 = x ]est également vrai si $1est par exemple " -o x". Essayez sh -xc '[ x$1 = x ] && echo yes' sh ' -o x'. [ x$1 = x ]est faux et n'a pas de sens.
Stéphane Chazelas
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.