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

j'ai vu des scripts bash tester pour la chaîne non-longueur zéro de deux façons différentes. La plupart des scripts utilisent l'option-n:

#!/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, ce qui est la meilleure façon de tester la longueur zéro:

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

ou

if [ ! "$var" ]; then
  # Do something when var is zero-length
fi
134
demandé sur codeforester 2010-10-06 06:12:05

6 réponses

Edit: C'est une version plus complète qui montre le plus de différences entre [ (aka test ) et [[ .

le tableau suivant montre si une variable est citée ou non, si vous utilisez des crochets simples ou doubles et si la variable contient seulement un espace sont les choses qui affectent si l'utilisation d'un test avec ou sans -n/-z est adapté 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 n'est pas de longueur nulle, faites l'une des actions suivantes:

  • citer la variable entre crochets (colonne 2a)
  • utilisez -n et citez la variable entre crochets (colonne 4a)
  • utiliser des crochets doubles avec ou sans citer et avec ou sans -n (colonnes 1b - 4b)

dans la colonne 1a, à partir de la ligne marquée" deux", noter 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 sous-entendue par le" T "ou le" F " dans la colonne 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 dans les colonnes 3a et 5a sont causés par le fait que la valeur de la variable inclut un espace et que la variable n'est pas cotée. Encore une fois, comme indiqué dans les colonnes 3b et 5b, [[ évalue le contenu de la variable comme une chaîne.

si vous utilisez [ , la clé pour vous assurer que vous n'obtenez pas de résultats inattendus est de citer la variable. En utilisant [[ , ça n'a pas d'importance.

les messages d'erreur, qui sont supprimés, sont "unary operator expected" ou " binaire l'opérateur attend".

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

#!/bin/bash
# by Dennis Williamson
# 2010-10-06, revised 2010-11-10
# for /q/test-for-non-zero-length-string-in-bash-n-var-or-var-69910/"%-${w}s" "true"; }
f () { [[ $? == 1 ]] && printf "%-${w}s" "false " || printf "%-${w}s" "-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"'

while read -r d t
do
    printf "%-${dw}s: " "$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
309
répondu Dennis Williamson 2010-11-10 19:15:05

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"

True si la chaîne est vide:

[ -z "$var" ]
[[ -z $var ]]
test -z "$var"
! [ "$var" ]
! [[ $var ]]
! (( ${#var} ))
! let ${#var}
! test "$var"
8
répondu Steven Penny 2014-12-28 03:23:56

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 semblent propres et lisibles. Ils devraient suffire dans la plupart des cas.

notez que nous n'avons pas besoin de citer les extensions variables à l'intérieur de [[ car il n'y a aucun danger de fractionnement de mots et globbing .

rares cas

Dans le cas rare d'avoir à faire une distinction entre "être définie à une chaîne vide (" vs "n'étant pas définie", nous pourrions utiliser ces:

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 test -v :

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

plus de discussion

il y a beaucoup de questions et de réponses à ce sujet. Voici un quelques:

6
répondu codeforester 2018-09-14 23:33:23

utiliser case/esac pour tester

case "$var" in
  "") echo "zero length";;
esac
2
répondu ghostdog74 2010-10-06 02:49:47

une façon alternative et peut-être plus transparente d'évaluer une variable env vide est d'utiliser...

  if [ "x$ENV_VARIABLE" != "x" ] ; then
      echo 'ENV_VARIABLE contains something'
  fi
2
répondu user1310789 2016-04-06 10:22:13

la bonne réponse est la suivante:

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

notez l'utilisation du [[...]] , qui gère correctement la citation des variables pour vous.

0
répondu user2592126 2018-04-13 21:47:56