Tester si une variable est vide dans un script shell

27

J'ai vu la technique suivante utilisée plusieurs fois sur de nombreux shells différents, pour tester si une variable est vide:

if [ "x$1" = "x" ]; then 
    # Variable is empty
fi

Y a-t-il des avantages à utiliser cela par rapport aux plus canoniques if [ -z "$1" ]? Serait-ce un problème de portabilité?

rahmu
la source

Réponses:

17

Certains shells historiques ont implémenté un analyseur très simple qui pourrait être confondu par des choses comme [ -n = "" ]où le premier opérande =ressemble à un opérateur, et analyserait cela comme [ -n = ]ou provoquerait une erreur de syntaxe. Dans [ "x$1" = x"" ], le xpréfixe garantit que x"$1"cela ne peut pas ressembler à un opérateur, et donc la seule façon dont le shell peut analyser ce test est de le traiter =comme un opérateur binaire.

Tous les shells modernes, et même la plupart des shells plus anciens encore en fonctionnement, suivent les règles POSIX qui exigent que toutes les expressions de test jusqu'à 4 mots soient analysées correctement. Il en [ -z "$1" ]va de même pour tester correctement si $1est vide et [ "$x" = "$y" ]pour tester l'égalité de deux variables.

Même certains shells actuels peuvent être confondus avec des expressions plus longues, et quelques expressions sont en fait ambiguës, évitez donc d'utiliser les opérateurs -aet -opour construire des tests booléens plus longs, et utilisez plutôt des appels distincts à [et les opérateurs booléens &&et propres du shell ||.

Gilles 'SO- arrête d'être méchant'
la source
3
Ce ne sont pas seulement des coquilles historiques . Certains ksh88 basés shsur certains Unices commerciaux ont toujours ce problème. Voir ici pour plus de détails.
Stéphane Chazelas
Cette déclaration est incorrecte: [ -z "$1" ]est un moyen approprié de tester si $1est vide . sh -c '[ -z "$1" ]' ''; sh -c '[ -z "$1" ]'- les deux renvoient 0, mais dans le second cas $1ne peuvent pas être vides car il n'existe pas.
mikeserv
3

Les tests ci-dessus provoqueront également une erreur si vous exécutez avec "set -u" ou "set -o nounset"

Une façon plus stable de vérifier une variable vide serait d'utiliser l' expansion des paramètres :

MYVAR = $ {MYVAR: - "Mauvaise valeur"}

Cette méthode fonctionne pour le shell bourne traditionnel, ainsi que pour ksh et bash.

Scott Hoffman
la source
2
Je crois que ceci est écrit comme -> M = $ {M: - "Bad Value"}
Gyan
0
    function isBlank {
 valueNoSpaces=$(echo "$@" | tr -d ' ')

 if [  "$valueNoSpaces" == null ] || [ -z "$valueNoSpaces" ] 
 then
       echo true ;
 else
       echo ""  ;
 fi
}

#Test
if [ $(isBlank "      ") ] 
then
    echo "isBlank \"      \" : it's blank"
else
    echo " isBlank \"      \": it is not blank"
fi

if [ $(isBlank "abc") ] 

then
    echo "isBlank \"abc\" : it's blank"
else
    echo "isBlank \"abc\" :it is not blank"
fi

if [ $(isBlank null) ] 
then
      echo "isBlank null : it's blank"
else
    echo "isBlank null : it is not blank"
fi

if [ $(isBlank "") ] 
then
    echo "isBlank \"\" : it's blank"
else
    echo "isBlank \"\" : it is not blank"
fi

#Result
isBlank "      " : it's blank

isBlank "abc" :it is not blank

isBlank null : it's blank

isBlank "" : it's blank
aslam mohammed
la source
3
Salut! Je ne sais pas comment cela répond à la question, qui demande pourquoi utiliser =versus -z, maintenant comment.
dhag