web-dev-qa-db-fra.com

Test d'une variable Bash non définie, en utilisant une fonction

Un simple test de variable Bash va:

${varName:?    "${varName} is not defined"}

Je voudrais réutiliser ceci, en le mettant dans une fonction . Comment s'il vous plaît?

La suite échoue

#
# Test a variable exists
tvar(){
 val=${1:?    "${1}    must be defined, preferably in $basedir"}
 if [ -z ${val}  ]
     then 
     echo Zero length value 
 else
     echo ${1} exists, value ${1}
 fi
}

C'est à dire. Je dois quitter si le test échoue.

28
DaveP

Grâce à lhunath answer, j'ai été amené à une partie de la page Bash man que j'ai négligée des centaines de fois:

 Lorsque vous n’effectuez pas l’extension de la sous-chaîne, bash teste un paramètre qui 
 est non défini ou nul; l'omission des deux-points donne un test uniquement pour un parame ‐
 ter qui est non réglé .

Cela m'a incité à créer la table de vérité suivante:


 | non défini | ensemble | définir et | sens
 | | mais nul | non null | 
 ============ + ======= + ========== + ========= + ======= ======================. $ {var-_} | T | F | T | non nul ou non défini 
 ------------ + ------- + ---------- + ---------- + ------- ----------------------
 $ {var: -_} | T | T | T | toujours vrai, utilisez pour subst .
 ------------ + ------- + ---------- + ---------- + ------- ----------------------
 $ var | F | F | T | var est défini et non null 
 ------------ + ------- + ---------- + ---------- + ------- ----------------------
 $ {! var [@]} | F | T | T | var est défini 

Ce tableau présente la spécification dans la dernière ligne. La page Bash man indique "Si name n'est pas un tableau, passe à 0 si name est défini et null sinon." Aux fins de cette table de vérité, elle se comporte de la même manière, même s'il s'agit d'un tableau.

46
Dennis Williamson

Ce que vous recherchez, c'est l'indirection.

assertNotEmpty() {
    : "${!1:? "$1 is empty, aborting."}"
}

Cela provoque l’abandon du script avec un message d’erreur si vous faites quelque chose comme ceci:

$ foo=""
$ assertNotEmpty foo
bash: !1:  foo is empty, aborting.

Si vous voulez juste tester si foo est vide, au lieu d’abandonner le script, utilisez ceci au lieu d’une fonction:

[[ $foo ]]

Par exemple:

until read -p "What is your name? " name && [[ $name ]]; do
    echo "You didn't enter your name.  Please, try again." >&2
done

Notez également qu'il existe une différence très importante entre un paramètre empty et un paramètre unset. Veillez à ne pas confondre ces termes! Un paramètre vide est un paramètre défini, mais défini sur une chaîne vide. Un paramètre non défini est un paramètre qui n'existe pas du tout.

Les exemples précédents testent tous les paramètres empty. Si vous voulez tester les paramètres unset et considérer tous les paramètres définis comme étant corrects, qu'ils soient vides ou non, utilisez ceci:

[[ ! $foo && ${foo-_} ]]

Utilisez-le dans une fonction comme celle-ci:

assertIsSet() {
    [[ ! ${!1} && ${!1-_} ]] && {
        echo "$1 is not set, aborting." >&2
        exit 1
    }
}

Ce qui n'abandonne le script que lorsque le nom du paramètre que vous transmettez dénote un paramètre non défini:

$ ( foo="blah"; assertIsSet foo; echo "Still running." )
Still running.
$ ( foo=""; assertIsSet foo; echo "Still running." )
Still running.
$ ( unset foo; assertIsSet foo; echo "Still running." )
foo is not set, aborting.
19
lhunath

Vous voulez utiliser [ -z ${parameter+Word} ]

Une partie de man bash:

Parameter Expansion
    ...
    In  each  of  the cases below, Word is subject to tilde expansion, parameter expansion, command substitution, and
    arithmetic expansion.  When not performing substring expansion, bash tests for a parameter that is unset or null;
    omitting the colon results in a test only for a parameter that is unset.
    ...
    ${parameter:+Word}
           Use Alternate Value.  If parameter is null or unset, nothing is substituted, otherwise  the  expansion  of
           Word is substituted.
    ...

en d'autres termes:

    ${parameter+Word}
           Use Alternate Value.  If parameter is unset, nothing is substituted, otherwise  the  expansion  of
           Word is substituted.

quelques exemples:

$ set | grep FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
it is unset
$ declare FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ FOOBAR=
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ FOOBAR=1
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ unset FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
it is unset
$
5
dnozay

Cette fonction teste les variables EN COURS. La variable peut même être un tableau. Notez que dans bash: 0 == VRAI, 1 == FAUX.

function var.defined {
    eval '[[ ${!'$1'[@]} ]]'
}

# Typical Usage of var.defined {}

declare you="Your Name Here" ref='you';

read -p "What's your name: " you;

if var.defined you; then   # Simple demo using literal text

    echo "BASH recognizes $you";
    echo "BASH also knows a reference to $ref as ${!ref}, by indirection."; 

fi

unset you # have just been killed by a master :D

if ! var.defined $ref; then    # Standard demo using an expanded literal value

    echo "BASH doesn't know $ref any longer";

fi

read -s -N 1 -p "Press any key to continue...";
echo "";

Donc, pour être clair ici, la fonction teste le texte littéral. A chaque fois qu'une commande est appelée dans bash, les variables sont généralement "remplacées" ou "substituées" par la valeur sous-jacente, sauf si:

  • $ varRef ($) est échappé:\$ varRef
  • $ varRef est un guillemet simple '$ varRef'
3
user735796

Je ne sais pas si c'est exactement ce que vous voulez, mais un truc pratique que j'utilise pour écrire un nouveau script + complexe consiste à utiliser "set -o"

set -o #mettra le script exploser quand il trouvera une variable non définie

PAR EXEMPLE:

$ grep '$ 1' chex.sh

case "$ 1" dans

$ ./chex.sh 

./chex.sh: ligne 111: $ 1: variable non liée

$ ./chex.sh foo

incorrect/aucune option transmise .. sortie

1
user381689

Je n'ai pas compris exactement de quoi avez-vous besoin. J'essaie de vous répondre malgré cela.

C'est à dire. Je dois quitter si le test échoue.

Le code:

${varName:?    "${varName} is not defined"}

retournera un code de sortie non nul lorsqu'il n'y a pas de variable nommée "nomVar". Le code de sortie de la dernière commande est enregistré dans $?.

A propos de votre code:

val=${1:?    "${1}    must be defined, preferably in $basedir"}

Peut-être qu'il ne fait pas ce dont vous avez besoin. Si $1 n'est pas défini, "${1}" sera remplacé par rien. Vous voulez probablement utiliser les guillemets simples qui écrivent littéralement ${1} sans substitution.

val=${1:?    '${1}    must be defined, preferably in $basedir'
1
Andrea Francia
if set | grep -q '^VARIABLE='
then 
    echo VARIABLE is set
fi
0
Emery Lapinski