213 votes

Test pour une chaîne de longueur non nulle dans Bash : [ -n "$var" ] ou [ "$var" ].

J'ai vu des scripts Bash scripts tester une chaîne de longueur non nulle de deux manières différentes. La plupart des scripts utilisent la fonction -n option :

#!/bin/bash
# With the -n option
if [ -n "$var" ]; then
  # Do something when var is non-zero length
fi

Mais l'option -n n'est pas vraiment nécessaire :

# Without the -n option
if [ "$var" ]; then
  # Do something when var is non-zero length
fi

Quelle est la meilleure solution ?

De même, quelle est la meilleure méthode pour tester la longueur zéro ?

if [ -z "$var" ]; then
  # Do something when var is zero-length
fi

o

if [ ! "$var" ]; then
  # Do something when var is zero-length
fi

458voto

Dennis Williamson Points 105818

Editar: Il s'agit d'une version plus complète qui montre davantage les différences entre [ (alias test ) et [[ .

Le tableau suivant montre que le fait qu'une variable soit citée ou non, que vous utilisiez des parenthèses simples ou doubles et que la variable ne contienne qu'un espace sont les éléments qui influent sur l'utilisation d'un test avec ou sans -n/-z convient pour vérifier une variable.

     | 1a    2a    3a    4a    5a    6a   | 1b    2b    3b    4b    5b    6b
     | [     ["    [-n   [-n"  [-z   [-z" | [[    [["   [[-n  [[-n" [[-z  [[-z"
-----+------------------------------------+------------------------------------
unset| false false true  false true  true | false false false false true  true
null | false false true  false true  true | false false false false true  true
space| false true  true  true  true  false| true  true  true  true  false false
zero | true  true  true  true  false false| true  true  true  true  false false
digit| true  true  true  true  false false| true  true  true  true  false false
char | true  true  true  true  false false| true  true  true  true  false false
hyphn| true  true  true  true  false false| true  true  true  true  false false
two  | -err- true  -err- true  -err- false| true  true  true  true  false false
part | -err- true  -err- true  -err- false| true  true  true  true  false false
Tstr | true  true  -err- true  -err- false| true  true  true  true  false false
Fsym | false true  -err- true  -err- false| true  true  true  true  false false
T=   | true  true  -err- true  -err- false| true  true  true  true  false false
F=   | false true  -err- true  -err- false| true  true  true  true  false false
T!=  | true  true  -err- true  -err- false| true  true  true  true  false false
F!=  | false true  -err- true  -err- false| true  true  true  true  false false
Teq  | true  true  -err- true  -err- false| true  true  true  true  false false
Feq  | false true  -err- true  -err- false| true  true  true  true  false false
Tne  | true  true  -err- true  -err- false| true  true  true  true  false false
Fne  | false true  -err- true  -err- false| true  true  true  true  false false

Si vous voulez savoir si une variable a une longueur non nulle, effectuez l'une des opérations suivantes :

  • citer la variable entre parenthèses simples (colonne 2a)
  • utiliser -n et citer la variable entre parenthèses simples (colonne 4a)
  • utiliser des doubles crochets avec ou sans citation et avec ou sans -n (colonnes 1b - 4b)

Remarquez dans la colonne 1a à partir de la ligne intitulée "deux" que le résultat indique que [ évalue le contenu de la variable comme s'ils faisaient partie de l'expression conditionnelle (le résultat correspond à l'assertion impliquée par le "T" ou le "F" dans la colonne de description). Lorsque [[ est utilisé (colonne 1b), le contenu de la variable est considéré comme une chaîne de caractères et n'est pas évalué.

Les erreurs des colonnes 3a et 5a sont dues au fait que la valeur de la variable comprend un espace et que la variable n'est pas citée. De nouveau, comme le montrent les colonnes 3b et 5b, [[ évalue le contenu de la variable comme une chaîne de caractères.

De même, pour les tests de chaînes de longueur nulle, les colonnes 6a, 5b et 6b montrent les manières correctes de procéder. Notez également que n'importe lequel de ces tests peut être annulé si la négation présente une intention plus claire que l'utilisation de l'opération inverse. Par exemple : if ! [[ -n $var ]] .

Si vous utilisez [ Pour être sûr de ne pas obtenir de résultats inattendus, il faut citer la variable. Utilisation de [[ ça n'a pas d'importance.

Les messages d'erreur, qui sont supprimés, sont "opérateur unaire attendu" ou "opérateur binaire attendu".

C'est le script qui a produit le tableau ci-dessus.

#!/bin/bash
# by Dennis Williamson
# 2010-10-06, revised 2010-11-10
# for http://stackoverflow.com/q/3869072
# designed to fit an 80 character terminal

dw=5    # description column width
w=6     # table column width

t () { printf '%-*s' "$w" " true"; }
f () { [[ $? == 1 ]] && printf '%-*s' "$w" " false" || printf '%-*s' "$w" " -err-"; }

o=/dev/null

echo '     | 1a    2a    3a    4a    5a    6a   | 1b    2b    3b    4b    5b    6b'
echo '     | [     ["    [-n   [-n"  [-z   [-z" | [[    [["   [[-n  [[-n" [[-z  [[-z"'
echo '-----+------------------------------------+------------------------------------'

while read -r d t
do
    printf '%-*s|' "$dw" "$d"

    case $d in
        unset) unset t  ;;
        space) t=' '    ;;
    esac

    [ $t ]        2>$o  && t || f
    [ "$t" ]            && t || f
    [ -n $t ]     2>$o  && t || f
    [ -n "$t" ]         && t || f
    [ -z $t ]     2>$o  && t || f
    [ -z "$t" ]         && t || f
    echo -n "|"
    [[ $t ]]            && t || f
    [[ "$t" ]]          && t || f
    [[ -n $t ]]         && t || f
    [[ -n "$t" ]]       && t || f
    [[ -z $t ]]         && t || f
    [[ -z "$t" ]]       && t || f
    echo

done <<'EOF'
unset
null
space
zero    0
digit   1
char    c
hyphn   -z
two     a b
part    a -a
Tstr    -n a
Fsym    -h .
T=      1 = 1
F=      1 = 2
T!=     1 != 2
F!=     1 != 1
Teq     1 -eq 1
Feq     1 -eq 2
Tne     1 -ne 2
Fne     1 -ne 1
EOF

1 votes

Merci. J'ai décidé d'adopter le style "citer la variable entre parenthèses simples (colonne 2a)". IMO, le -n ajoute juste du bruit et diminue la lisibilité. De même, pour les tests de longueur zéro ou unset, je vais utiliser [ ! "$var" ] au lieu de [ -z "$var" ].

3 votes

Donc votre graphique pour [" vs [-n" (la première question de l'OP) montre qu'ils sont complètement équivalents, n'est-ce pas ?

1 votes

@hobs : Oui, et celui à utiliser dépend de celui qui est le plus clair. Vous remarquerez également que leur équivalent est la forme à double parenthèse qui est préférée lorsqu'on utilise Bash.

41voto

codeforester Points 17582

Il est préférable d'utiliser le plus puissant [[ en ce qui concerne Bash.

Cas habituels

if [[ $var ]]; then   # var is set and it is not empty
if [[ ! $var ]]; then # var is not set or it is set to an empty string

Les deux constructions ci-dessus sont propres et lisibles. Elles devraient suffire dans la plupart des cas.

Notez que nous n'avons pas besoin de citer les expansions de variables à l'intérieur de [[ car il n'y a aucun risque de division des mots y globbing .

Pour éviter shellcheck Les plaintes légères de l'UE concernant [[ $var ]] y [[ ! $var ]] nous pourrions utiliser le -n option.

Cas rares

Dans le cas rare où nous devrions faire une distinction entre "être réglé sur une chaîne vide" et "ne pas être réglé du tout", nous pourrions utiliser ceux-ci :

if [[ ${var+x} ]]; then           # var is set but it could be empty
if [[ ! ${var+x} ]]; then         # var is not set
if [[ ${var+x} && ! $var ]]; then # var is set and is empty

Nous pouvons également utiliser le -v test :

if [[ -v var ]]; then             # var is set but it could be empty
if [[ ! -v var ]]; then           # var is not set
if [[ -v var && ! $var ]]; then   # var is set and is empty
if [[ -v var && -z $var ]]; then  # var is set and is empty

Postes et documentation connexes

Il y a beaucoup de messages liés à ce sujet. En voici quelques-uns :

12voto

Steven Penny Points 18523

Voici d'autres tests

Vrai si la chaîne n'est pas vide :

[ -n "$var" ]
[[ -n $var ]]
test -n "$var"
[ "$var" ]
[[ $var ]]
(( ${#var} ))
let ${#var}
test "$var"

Vrai si la chaîne est vide :

[ -z "$var" ]
[[ -z $var ]]
test -z "$var"
! [ "$var" ]
! [[ $var ]]
! (( ${#var} ))
! let ${#var}
! test "$var"

1voto

papacharlie Points 269

La réponse correcte est la suivante :

if [[ -n $var ]] ; then
  blah
fi

Notez l'utilisation du [[...]] qui s'occupe correctement de citer les variables pour vous.

0voto

user1310789 Points 1

Une manière alternative et peut-être plus transparente d'évaluer une variable d'environnement vide est d'utiliser...

  if [ "x$ENV_VARIABLE" != "x" ] ; then
      echo 'ENV_VARIABLE contains something'
  fi

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X