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)
Cela retournera vrai si une variable n'est pas définie ou définie sur la chaîne vide ("").
if [ -z "$VAR" ];
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} ]]
Une variable dans bash (et tout shell compatible POSIX) peut être dans l'un des trois états suivants:
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.
-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.
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
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.
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:
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 .
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").
les if-then et -z entiers sont inutiles.
["$ foo"] && echo "foo n'est pas vide" ["$ foo"] || echo "foo est en effet vide"
Cela est vrai exactement lorsque $ FOO est défini et vide:
[ "${FOO+x}" = x ] && [ -z "$FOO" ]
extension oneliner de la solution de duffbeer7 :
#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter
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
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).