Je vois cela souvent dans les scripts de construction de projets utilisant AutoTools (Autoconf, Automake). Lorsque quelqu'un veut vérifier la valeur d'une variable de coquille, ils utilisent fréquemment cet idiome:
if test "x$Shell_VAR" = "xyes"; then
...
Quel est l'avantage à ce sujet sur la simple vérification de la valeur comme celle-ci:
if test $Shell_VAR = "yes"; then
...
Je pense qu'il doit y avoir une raison pour laquelle je le vois si souvent, mais je ne peux pas comprendre ce que c'est.
Si vous utilisez une coquille qui fait simple Substitution et le Shell_VAR
variable n'existe pas (ou est vide), alors vous devez faire attention aux cas de bord. Les traductions suivantes vont arriver:
if test $Shell_VAR = yes; then --> if test = yes; then
if test x$Shell_VAR = xyes; then --> if test x = xyes; then
Les premiers de ceux-ci généreront une erreur depuis l'argument du poing à test
a disparu. La seconde n'a pas ce problème.
Votre cas traduit comme suit:
if test "x$Shell_VAR" = "xyes"; then --> if test "x" = "xyes"; then
Le x
, au moins pour les coquilles compatibles POSIX, est réellement redondant car les guillemets s'ensuivent qu'un argument vide et un espace contenant des espaces sont interprétés comme un seul objet.
L'autre raison que personne d'autre n'a encore été mentionnée est en rapport avec le traitement des options. Si vous écrivez:
if [ "$1" = "abc" ]; then ...
et $ 1 a la valeur '-n', la syntaxe de la commande de test est ambiguë; Ce n'est pas clair ce que vous testiez. Le 'X' à l'avant empêche un tiret de pointe de causer des problèmes.
Vous devez regarder des coquilles vraiment anciens pour en trouver un où la commande de test n'a pas de support pour -n
ou -z
; La commande 7 (1978) test
commande les incluses. Ce n'est pas tout à fait sans importance - certaines version 6 UNIX se sont échappées dans BSD, mais ces jours-ci, vous seriez extrêmement difficile de trouver tout ce qui est ancien dans l'utilisation actuelle.
L'utilisation de citations doubles autour des valeurs est dangereuse, car un certain nombre d'autres personnes ont souligné. En effet, s'il y a une chance que les noms de fichiers contiennent des espaces (MacOS X et Windows encouragent que dans une certaine mesure, et UNIX a toujours soutenu cela, bien que des outils tels que xargs
rendent plus difficile), alors vous devez inclure le fichier Les noms en citations doubles chaque fois que vous les utilisez aussi. Sauf si vous êtes responsable de la valeur (par exemple, lors de la manipulation des options et que vous définissez la variable sur "Non" au démarrage et "Oui" lorsqu'un indicateur est inclus dans la ligne de commande), il n'est pas sûr d'utiliser des formes de variables non cotées. Jusqu'à ce que vous les ayez prouvé sa sécurité - et vous pouvez aussi bien le faire tout le temps à plusieurs fins. Ou document que vos scripts échoueront horriblement si les utilisateurs tentent de traiter des fichiers avec des blancs dans les noms. (Et il y a d'autres personnages à craindre pour trop - les backtsticks pourraient être plutôt désagréables aussi, par exemple.)
Je connais deux raisons pour cette convention:
http://tldp.org/ldp/abs/html/comparon-ops.html
Dans un test composé, même citant la variable de chaîne pourrait ne pas suffire. [-N "$ string" -o "$ a" = "$ b"] peut provoquer une erreur avec certaines versions de bash si $ string est vide. Le moyen sûr est d'ajouter un caractère supplémentaire aux variables éventuellement vides, ["x $ string"! = X -o "x $ a" = "x $ b"] (l'annulation "X '''s" annuler).
Deuxièmement, dans d'autres coquilles que Bash, en particulier les plus âgées, les conditions de test comme '-Z' à tester pour une variable vide n'existaient pas, donc alors que cela:
if [ -z "$SOME_VAR" ]; then
echo "this variable is not defined"
fi
travaillera bien dans Bash, si vous visez la portabilité dans divers environnements UNIX où vous ne pouvez pas être sûr que la coque par défaut sera bash et si elle prend en charge la condition de test -Z, il est plus sûr d'utiliser le formulaire si [" x $ quelque chose_var "=" x "] car cela aura toujours l'effet prévu. Il s'agit essentiellement d'une vieille astuce de script shell pour trouver une variable vide, et il est toujours utilisé aujourd'hui pour la compatibilité à l'envers, malgré les méthodes plus propres disponibles.
Je recommande à la place:
if test "yes" = "$Shell_VAR"; then
depuis qu'il éloigne le laid x
, et résout toujours le problème mentionné par https://stackoverflow.com/a/174288/895245$Shell_VAR
peut commencer par -
et être lu comme une option.
Je crois que c'est due à
SHELLVAR=$(true)
if test $SHELLVAR = "yes" ; then echo "yep" ; fi
# bash: test: =: unary operator expected
aussi bien que
if test $UNDEFINEDED = "yes" ; then echo "yep" ; fi
# bash: test: =: unary operator expected
et
SHELLVAR=" hello"
if test $SHELLVAR = "hello" ; then echo "yep" ; fi
# yep
cependant, cela devrait généralement fonctionner
SHELLVAR=" hello"
if test "$SHELLVAR" = "hello" ; then echo "yep" ; fi
#<no output>
mais quand il se plaint dans la production ailleurs, il est difficile de dire ce que ses plaignants sont supposés, alors
SHELLVAR=" hello"
if test "x$SHELLVAR" = "xhello" ; then echo "yep" ; fi
fonctionne aussi bien, mais il serait plus facile de déboguer.
Je faisais cela dans DOS lorsque le shell_var peut être indéfini.
Si vous ne faites pas la chose "x $ shell_var", alors si $ shell_var est indéfini, vous obtenez une erreur sur "=" Ne pas être un opérateur monadique ou quelque chose comme ça.