web-dev-qa-db-fra.com

Comment déterminer si une variable bash est vide?

Quelle est la meilleure façon de déterminer si une variable dans bash est vide ("")?

J'ai entendu dire qu'il est recommandé de faire if [ "x$variable" = "x" ]

Est-ce la manière correcte? (il doit y avoir quelque chose de plus simple)

784
Brent

Cela retournera vrai si une variable n'est pas définie ou définie sur la chaîne vide ("").

if [ -z "$VAR" ];
1075
duffbeer703

Dans Bash, lorsque vous n'êtes pas concerné par la portabilité vers des shells qui ne la prennent pas en charge, vous devez toujours utiliser la syntaxe à double crochet:

L'un des éléments suivants:

if [[ -z $variable ]]
if [[ -z "$variable" ]]
if [[ ! $variable ]]
if [[ ! "$variable" ]]

Dans Bash, en utilisant des crochets doubles, les guillemets ne sont pas nécessaires. Vous pouvez simplifier le test d'une variable qui contient une valeur pour:

if [[ $variable ]]

Cette syntaxe est compatible avec ksh (au moins ksh93, de toute façon). Il ne fonctionne pas dans les shells POSIX purs ou Bourne plus anciens tels que sh ou dash.

Voir ma réponse ici et BashFAQ/031 pour plus d'informations sur les différences entre les crochets doubles et simples.

Vous pouvez tester pour voir si une variable est spécifiquement non définie (par opposition à une chaîne vide):

if [[ -z ${variable+x} ]]

où le "x" est arbitraire.

Si vous voulez savoir si une variable est nulle mais pas non définie:

if [[ -z $variable && ${variable+x} ]]
253

Une variable dans bash (et tout shell compatible POSIX) peut être dans l'un des trois états suivants:

  • désarmé
  • défini sur la chaîne vide
  • défini sur une chaîne non vide

La plupart du temps, il vous suffit de savoir si une variable est définie sur une chaîne non vide, mais il est parfois important de distinguer entre non défini et défini sur la chaîne vide.

Voici des exemples de la façon dont vous pouvez tester les différentes possibilités, et cela fonctionne dans bash ou tout shell compatible POSIX:

if [ -z "${VAR}" ]; then
    echo "VAR is unset or set to the empty string"
fi
if [ -z "${VAR+set}" ]; then
    echo "VAR is unset"
fi
if [ -z "${VAR-unset}" ]; then
    echo "VAR is set to the empty string"
fi
if [ -n "${VAR}" ]; then
    echo "VAR is set to a non-empty string"
fi
if [ -n "${VAR+set}" ]; then
    echo "VAR is set, possibly to the empty string"
fi
if [ -n "${VAR-unset}" ]; then
    echo "VAR is either unset or set to a non-empty string"
fi

Voici la même chose mais sous forme de tableau pratique:

                        +-------+-------+-----------+
                VAR is: | unset | empty | non-empty |
+-----------------------+-------+-------+-----------+
| [ -z "${VAR}" ]       | true  | true  | false     |
| [ -z "${VAR+set}" ]   | true  | false | false     |
| [ -z "${VAR-unset}" ] | false | true  | false     |
| [ -n "${VAR}" ]       | false | false | true      |
| [ -n "${VAR+set}" ]   | false | true  | true      |
| [ -n "${VAR-unset}" ] | true  | false | true      |
+-----------------------+-------+-------+-----------+

La construction ${VAR+foo} Se développe dans la chaîne vide si VAR n'est pas définie ou dans foo si VAR est définie sur n'importe quoi (y compris la chaîne vide).

La construction ${VAR-foo} Se développe à la valeur de VAR si définie (y compris définie sur la chaîne vide) et foo si non définie. Ceci est utile pour fournir des valeurs par défaut remplaçables par l'utilisateur (par exemple, ${COLOR-red} Dit d'utiliser red sauf si la variable COLOR a été définie sur quelque chose).

La raison pour laquelle [ x"${VAR}" = x ] Est souvent recommandée pour tester si une variable est non définie ou définie sur la chaîne vide est parce que certaines implémentations de la commande [ (Également appelée test) sont buggy. Si VAR est défini sur quelque chose comme -n, Alors certaines implémentations feront la mauvaise chose quand on leur donnera [ "${VAR}" = "" ] Car le premier argument de [ Est interprété à tort comme l'opérateur -n, pas une chaîne.

239
Richard Hansen

-z est le meilleur moyen.

Une autre option que j'ai utilisée consiste à définir une variable, mais elle peut être remplacée par une autre variable, par exemple

export PORT=${MY_PORT:-5432}

Si la $MY_PORT la variable est vide, puis PORT est définie sur 5432, sinon PORT est défini sur la valeur de MY_PORT. Notez que la syntaxe inclut les deux points et le tiret.

38
Rory

Si vous êtes intéressé à distinguer les cas de statut set-empty contre unset, regardez l'option -u pour bash:

$ set -u
$ echo $BAR
bash: BAR: unbound variable
$ [ -z "$BAR" ] && echo true
bash: BAR: unbound variable
$ BAR=""
$ echo $BAR

$ [ -z "$BAR" ] && echo true
true
24
MikeyB

Un suppléant que j'ai vu pour [ -z "$foo" ] est le suivant, mais je ne sais pas pourquoi les gens utilisent cette méthode, quelqu'un le sait?

[ "x${foo}" = "x" ]

Quoi qu'il en soit, si vous interdisez les variables non définies (soit par set -u ou set -o nounset), vous rencontrerez des problèmes avec ces deux méthodes. Il existe une solution simple à cela:

[ -z "${foo:-}" ]

Remarque: cela laissera votre variable indéfinie.

8
errant.info

La question demande comment vérifier si une variable est une chaîne vide et les meilleures réponses sont déjà données pour cela.
Mais j'ai atterri ici après une période de programmation passée en php et ce que je cherchais en fait était une vérification comme la fonction vide dans php fonctionnant dans un shell bash.
Après avoir lu les réponses, j'ai réalisé que je ne pensais pas correctement en bash, mais de toute façon à ce moment une fonction comme vide en php aurait été tellement pratique dans mon code bash.
Comme je pense que cela peut arriver à d'autres, j'ai décidé de convertir la fonction vide php en bash

Selon le manuel php :
une variable est considérée comme vide si elle n'existe pas ou si sa valeur est l'une des suivantes:

  • "" (une chaîne vide)
  • 0 (0 as an integer)
  • 0,0 (0 comme flottant)
  • "0" (0 sous forme de chaîne)
  • un tableau vide
  • une variable déclarée, mais sans valeur

Bien sûr, les cas null et false ne peuvent pas être convertis en bash, ils sont donc omis.

function empty
{
    local var="$1"

    # Return true if:
    # 1.    var is a null string ("" as empty string)
    # 2.    a non set variable is passed
    # 3.    a declared variable or array but without a value is passed
    # 4.    an empty array is passed
    if test -z "$var"
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is zero (0 as an integer or "0" as a string)
    Elif [ "$var" == 0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return

    # Return true if var is 0.0 (0 as a float)
    Elif [ "$var" == 0.0 2> /dev/null ]
    then
        [[ $( echo "1" ) ]]
        return
    fi

    [[ $( echo "" ) ]]
}



Exemple d'utilisation:

if empty "${var}"
    then
        echo "empty"
    else
        echo "not empty"
fi



Démo:
l'extrait de code suivant:

#!/bin/bash

vars=(
    ""
    0
    0.0
    "0"
    1
    "string"
    " "
)

for (( i=0; i<${#vars[@]}; i++ ))
do
    var="${vars[$i]}"

    if empty "${var}"
        then
            what="empty"
        else
            what="not empty"
    fi
    echo "VAR \"$var\" is $what"
done

exit

les sorties:

VAR "" is empty
VAR "0" is empty
VAR "0.0" is empty
VAR "0" is empty
VAR "1" is not empty
VAR "string" is not empty
VAR " " is not empty

Cela dit, dans une logique bash, les vérifications sur zéro dans cette fonction peuvent provoquer des problèmes secondaires à mon humble avis, toute personne utilisant cette fonction devrait évaluer ce risque et peut-être décider de supprimer ces vérifications en ne laissant que la première .

6
Luca Borrione

Mes 5 cents: il y a aussi une syntaxe plus courte que if ..., celui-là:

VALUE="${1?"Usage: $0 value"}"

Cette ligne définira VALUE si un argument a été fourni et affichera un message d'erreur précédé du numéro de ligne de script en cas d'erreur (et mettra fin à l'exécution du script).

Un autre exemple peut être trouvé dans le abs-guide (recherchez "Exemple 10-7").

5
gluk47

les if-then et -z entiers sont inutiles.

 ["$ foo"] && echo "foo n'est pas vide" 
 ["$ foo"] || echo "foo est en effet vide" 
5
namewithoutwords

Cela est vrai exactement lorsque $ FOO est défini et vide:

[ "${FOO+x}" = x ] && [ -z "$FOO" ]
4
JHS

extension oneliner de la solution de duffbeer7 :

#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter
4
andrej

Personnellement, je préfère un moyen plus clair de vérifier:

if [ "${VARIABLE}" == "" ]; then
  echo VARIABLE is empty
else
  echo VARIABLE is not empty
fi
4
Fedir RYKHTIK

Pas une réponse exacte, mais a rencontré cette astuce. Si la chaîne que vous recherchez provient d'une "commande", vous pouvez en fait stocker la commande dans un env. puis exécutez-la à chaque fois pour l'instruction if, aucun crochet n'est requis!

Par exemple, cette commande, qui détermine si vous êtes sur Debian:

grep debian /proc/version

exemple complet:

IS_DEBIAN="grep -i debian /proc/version"

if $IS_DEBIAN; then
  echo 'yes debian'
else
  echo 'non debian'
fi

C'est donc comme un moyen indirect (en le réexécutant à chaque fois) de vérifier une chaîne vide (il se trouve qu'il vérifie la réponse d'erreur de la commande, mais il se trouve également qu'il renvoie une chaîne vide).

0
rogerdpack