Question Comment déterminer si une variable bash est vide?


Quel est le meilleur moyen de déterminer si une variable de bash est vide ("")?

J'ai entendu dire qu'il est recommandé que je fasse if [ "x$variable" = "x" ]

Est-ce le correct façon? (il doit y avoir quelque chose de plus simple)


719
2018-05-12 17:54


origine




Réponses:


Cela retournera true si une variable est non définie ou définie sur la chaîne vide ("").

if [ -z "$VAR" ];

980
2018-05-12 18:06



Est-ce que cela inclut si une variable IS SET a une valeur de ""? - Brent
Oui, c'est le cas ... "-z" teste une chaîne de longueur nulle. - David Z
if [ ! -z "$VAR" ]; - Aaron Copley
l'inverse de -z est -n  if [ -n "$VAR" ]; - Felipe Alvarez
Les guillemets doubles garantissent que la variable ne sera pas divisée. Un simple $var sur une ligne de commande sera divisé par son espace en une liste de paramètres, tandis que "$var" sera toujours un seul paramètre. Citer des variables est souvent une bonne pratique et vous évite de vous lancer dans des noms de fichiers contenant des espaces (entre autres). Exemple: après avoir fait a="x --help"essayer cat $a - cela vous donnera la page d'aide pour cat. Alors essaye cat "$a" - ce sera (généralement) dire cat: x --help: No such file or directory. En bref, citez tôt et citez souvent et vous ne le regretterez presque jamais. - Score_Under


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

N'importe lequel des éléments suivants:

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

Dans Bash, à l'aide de doubles crochets, les guillemets ne sont pas nécessaires. Vous pouvez simplifier le test pour une variable qui Est-ce que contenir une valeur pour:

if [[ $variable ]]

Cette syntaxe est compatible avec ksh (au moins ksh93, de toute façon). Il ne fonctionne pas avec les coquilles POSIX ou Bourne plus anciennes telles que sh ou dash.

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

Vous pouvez tester 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 null mais pas non définie:

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

227
2018-02-25 03:37



Cette if [[ $variable ]] a bien fonctionné pour moi et n’a même pas eu besoin de la set -u cela était requis par l'une des autres solutions proposées. - Teemu Leisti
Je pense que c'est mieux que la réponse acceptée. - qed
Pourquoi recommandez-vous une fonctionnalité non portable alors que cela ne présente aucun avantage? - Alastair Irvine
@AlastairIrvine: je mentionne la portabilité dans la première phrase de ma réponse, le titre et le corps de la question contiennent le mot "Bash" et la question est balisée frapper, et la structure à double support fournit avantages clairs De plusieurs façons. Et je ne recommande pas de mélanger les styles de support pour des raisons de cohérence et de facilité de maintenance. Si vous avez besoin de la portabilité maximale et minimale du dénominateur commun, utilisez sh au lieu de Bash. Si vous avez besoin des capacités accrues qu’il offre, utilisez Bash et utilisez-le pleinement. - Dennis Williamson
@BrunoBronosky: J'ai annulé l'édition. Il n'y a aucune exigence pour ; à la fin. le then peut être sur la ligne suivante sans un point-virgule. - Dennis Williamson


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

  • non fixé
  • mis à la chaîne vide
  • défini sur une chaîne non vide

La plupart du temps, il suffit de savoir si une variable est définie sur une chaîne non vide, mais il est parfois important de faire la distinction entre unset et 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 n’importe quel 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      |
+-----------------------+-------+-------+-----------+

le ${VAR+foo} la construction se développe à la chaîne vide si VAR est non réglé ou à foo si VAR est défini sur n'importe quoi (y compris la chaîne vide).

le ${VAR-foo} construire se développe à la valeur de VAR si défini (y compris la chaîne vide) et foo si non réglé. Ceci est utile pour fournir des valeurs par défaut remplaçables par l'utilisateur (par exemple, ${COLOR-red} dit d'utiliser red à moins que la variable COLOR a été mis à quelque chose).

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


205
2018-04-24 20:39



Le test d’une variable définie sur la chaîne vide peut également être effectué à l’aide de [ -z "${VAR-set}" ]. - nwellnhof
@nwellnhof: Merci! J'ai mis à jour ma réponse pour utiliser la syntaxe plus courte. - Richard Hansen
@FaheemMitha: Ce n'est pas votre faute - ma réponse était difficile à lire. J'ai ajouté un tableau pour que la réponse soit plus claire, espérons-le. - Richard Hansen
@ RichardHansen: Merci, c'est un ajout utile. - Faheem Mitha
Les contrôles non définis ne sont pas fiables. Si l'utilisateur a appelé set -u ou set -o nounset dans bash, le test entraînera simplement l'erreur "bash: VAR: variable non liée". Voir stackoverflow.com/a/13864829 pour un contrôle non défini plus fiable. Mon go-to vérifier si une variable est nulle ou non définie est [ -z "${VAR:-}" ]. Mon chèque pour savoir si une variable est non vide est [ "${VAR:-}" ]. - Kevin Jin


-z est le meilleur moyen.

Une autre option que j'ai utilisée est de 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, alors PORT est défini sur 5432, sinon PORT est défini sur la valeur MY_PORT. Notez que la syntaxe inclut les deux points et le tiret.


36
2018-06-11 13:19



J'ai trouvé cela accidentellement aujourd'hui, et c'était exactement ce que je voulais. Merci! Je dois tolérer set -o nounset dans certains scripts. - opello


Si vous souhaitez distinguer les cas d’état défini comme étant vide ou non défini, consultez 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
2018-05-12 18:21





Un remplaçant que j'ai vu [ -z "$foo" ] est ce qui suit, mais je ne suis pas sûr de savoir pourquoi les gens utilisent cette méthode, est-ce que quelqu'un le sait?

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

Quoi qu’il en soit, si vous n'autorisez pas les variables non définies (soit par set -u ou set -o nounset), alors vous aurez des problèmes avec ces deux méthodes. Il y a une solution simple à ceci:

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

Note: cela laissera votre variable undef.


8
2017-10-20 03:58



Il y a un commentaire sur l'alternative à -z à pubs.opengroup.org/onlinepubs/009695399/utilities/test.html. Fondamentalement, il ne s'agit pas d'une alternative à -z. Au contraire, il gère les cas où $foo pourrait s'étendre à quelque chose commençant par un métacaractère qui [ ou test serait confondu par. Mettre un non-métacaractère arbitraire au début élimine cette possibilité. - James Sneeringer


le 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 passée en programmation en php et ce que j’étais en train de chercher était un chèque comme le fonction vide en php travaillant dans un shell bash.
Après avoir lu les réponses, je me suis rendu compte que je ne pensais pas correctement à Bash, mais de toute façon, à cet instant, 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 php empty en bash

Selon le php manuel:
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 sous forme d'entier)
  • 0.0 (0 en float)
  • "0" (0 sous forme de chaîne)
  • un tableau vide
  • une variable déclarée, mais sans valeur

Bien sur le nul et faux les cas 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 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 de bash, les vérifications de zéro dans cette fonction peuvent entraîner des problèmes secondaires, toute personne utilisant cette fonction devrait évaluer ce risque et décider éventuellement de supprimer ces vérifications en ne laissant que le premier.


6
2017-08-31 20:11



À l'intérieur de la fonction empty - pourquoi as-tu écrit [[ $( echo "1" ) ]] ; return au lieu de simplement return 1 ? - Dor