Bash test pour la chaîne vide avec X"" [dupliquer]

cette question a déjà une réponse ici:

je sais que je peux tester une chaîne vide en Bash avec -z comme suit:

if [[ -z $myvar ]]; then do_stuff; fi

mais je vois beaucoup de code écrit comme:

if [[ X"" = X"$myvar" ]]; then do_stuff; fi

est-ce que cette méthode est plus portable? Est-ce que c'est juste une miette historique d'avant les jours de -z ? Est-ce pour les shells POSIX (même si je l'ai vu utilisé dans les scripts ciblant bash )? Prêt pour ma leçon d'histoire/de portabilité.


la même question a été posée sur la faute du serveur que Comment déterminer si une variable bash est vide? mais personne n'a offert une explication quant à pourquoi vous voyez le code avec le truc X"" .

73
demandé sur Community 2011-07-28 03:50:33

2 réponses

fondamentalement, parce que dans les temps maintenant lointains, le comportement de test était plus complexe et pas défini uniformément à travers les différents systèmes (donc le code portable a dû être écrit avec soin pour éviter les constructions non-portables).

en particulier, avant que test soit un shell intégré, C'était un exécutable séparé (et notez que MacOS X a toujours /bin/test et /bin/[ comme exécutables). Quand ce fut le cas, en écrivant:

if [ -z $variable ]

quand $variable était vide invoquerait le programme d'essai via son alias [ avec 3 arguments:

argv[0] = "["
argv[1] = "-z"
argv[2] = "]"

parce que la variable était vide donc il n'y avait rien à étendre. Ainsi, la façon sûre d'écrire le code était:

if [ -z "$variable" ]

cela fonctionne de manière fiable, en passant 4 arguments à l'exécutable test . Certes, le programme d'essai a été intégré à la plupart des coquilles depuis des décennies, mais de vieux équipements les bonnes pratiques apprises il y a encore plus longtemps.

l'autre problème résolu par le préfixe X est ce qui est arrivé si les variables incluent des tirets de tête, ou contiennent des égaux ou d'autres comparateurs. Considérons (un mauvais exemple):

x="-z"
if [ $x -eq 0 ]

est-ce un test de chaîne vide avec un argument errant (erroné), ou un test d'égalité numérique avec un premier argument non numérique? Différents systèmes ont fourni des réponses différentes avant POSIX a normalisé le comportement, vers 1990. Ainsi, la façon sûre de traiter avec ceci était:

if [ "X$x" = "X0" ]

ou, plus généralement, dans mon expérience, mais complètement, de manière équivalente):

if [ X"$x" = X"0" ]

il était tous les cas de bord comme celui-ci, lié à la possibilité que le test était un exécutable séparé, ce qui signifie que le code shell portable utilise toujours des guillemets doubles plus copieusement que les coquilles modernes exigent réellement, et la notation du préfixe X était utilisé pour s'assurer que les choses ne pourraient pas être mal interprétées.

113
répondu Jonathan Leffler 2012-04-06 14:19:46

Ah, c'est une de mes questions et réponses préférées, parce que j'ai trouvé la réponse en y pensant. Le X est défini juste au cas où la chaîne commence avec un - , qui peut être pris comme un drapeau pour le test. Mettre un X avant vient de supprimer ce cas, et la comparaison peut encore tenir.

j'aime aussi cela parce que ce genre de truc est presque un héritage du passé, des temps les plus anciens de l'informatique, et vous le rencontrez lorsque vous essayez de lire certains des scripts shell les plus portables (autoconf, configure, etc.)

10
répondu Diego Sevilla 2011-07-28 00:01:34