from - variable assignment bash shell script




Wie überprüft man, ob eine Variable in Bash gesetzt ist? (20)

Functions to check if variable is declared/unset

including empty $array=()


The following functions test if the given name exists as a variable

# The first parameter needs to be the name of the variable to be checked.
# (See example below)

var_is_declared() {
    { [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}

var_is_unset() {
    { [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;} 
}
  • By first testing if the variable is (un)set, the call to declare can be avoided, if not necessary.
  • If however $1 contains the name of an empty $array=() , the call to declare would make sure we get the right result
  • There's never much data passed to /dev/null as declare is only called if either the variable is unset or an empty array.

This functions would test as showed in the following conditions:

a;       # is not declared
a=;      # is declared
a="foo"; # is declared
a=();    # is declared
a=("");  # is declared
unset a; # is not declared

a;       # is unset
a=;      # is not unset
a="foo"; # is not unset
a=();    # is not unset
a=("");  # is not unset
unset a; # is unset

.

For more details

and a test script see my answer to the question "How do I check if a variable exists in bash?" .

Anmerkung: Die ähnliche Verwendung von declare -p, wie es auch gezeigt ‚s answer ist wirklich zufällig. Sonst hätte ich es natürlich gutgeschrieben!

Woher weiß ich, ob eine Variable in Bash gesetzt ist?

Wie überprüfe ich zum Beispiel, ob der Benutzer einer Funktion den ersten Parameter gegeben hat?

function a {
    # if $1 is set ?
}

Der richtige Weg

if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi

Wobei ${var+x} eine Parametererweiterung ist, die zu nichts führt, wenn var ist, und andernfalls die Zeichenfolge x .

Zitate Exkurs

Zitate können weggelassen werden (also können wir ${var+x} anstelle von "${var+x}" sagen), weil diese Syntax & Verwendung garantiert, dass sie nur zu etwas erweitert wird, das keine Anführungszeichen benötigt (da sie entweder auf x (was keine Wortumbrüche enthält, so dass es keine Anführungszeichen benötigt) oder zu nichts (was zu [ -z ] , was praktischerweise zu demselben Wert (wahr) führt, der auch [ -z "" ] )).

Während jedoch Zitate sicher weggelassen werden können, und es war nicht sofort für alle offensichtlich (es war nicht einmal der erste Autor dieser Zitate Erklärung, die auch eine große Bash-Codierer ist), wäre es manchmal besser, die Lösung zu schreiben mit Anführungszeichen als [ -z "${var+x}" ] , zu den sehr kleinen möglichen Kosten einer O (1) Geschwindigkeitsstrafe. Der erste Autor hat dies auch als Kommentar neben dem Code hinzugefügt, indem er diese Lösung verwendet, die die URL zu dieser Antwort enthält, die jetzt auch die Erklärung enthält, warum die Anführungszeichen sicher weggelassen werden können.

Der falsche Weg

if [ -z "$var" ]; then echo "var is unset"; else echo "var is set to '$var'"; fi

Dies liegt daran, dass nicht zwischen einer Variablen, die nicht gesetzt ist, und einer Variablen, die auf die leere Zeichenfolge festgelegt ist, unterschieden wird. Das heißt, wenn var='' , dann wird die obige Lösung falsch ausgeben, dass var nicht gesetzt ist.

Diese Unterscheidung ist jedoch in Situationen wichtig, in denen der Benutzer eine Erweiterung oder eine zusätzliche Liste von Eigenschaften angeben muss und diese nicht standardmäßig einen nicht leeren Wert angibt, während die Angabe einer leeren Zeichenfolge dem Skript die Verwendung einer leeren Erweiterung oder Liste vorschreibt von zusätzlichen Eigenschaften.


Auf einer modernen Version von Bash (4.2 oder später, denke ich; ich weiß es nicht sicher) würde ich Folgendes versuchen:

if [ ! -v SOMEVARIABLE ] #note the lack of a $ sigil
then
    echo "Variable is unset"
elif [ -z "$SOMEVARIABLE" ]
then
    echo "Variable is set to an empty string"
else
    echo "Variable is set to some string"
fi

Das benutze ich jeden Tag:

#
# Check if a variable is set
#   param1  name of the variable
#
function is_set()
{
    [[ -n "${1}" ]] && test -n "$(eval "echo "\${${1}+x}"")"
}

Dies funktioniert gut unter Linux und Solaris bis bash 3.0.

bash-3.00$ myvar="TEST"
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ mavar=""
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ unset myvar
bash-3.00$ is_set myvar ; echo $?
1

Die obigen Antworten funktionieren nicht, wenn der Bash-Optionssatz set -u aktiviert ist. Sie sind auch nicht dynamisch, zB wie man eine Variable testet mit dem Namen "Dummy" definiert ist? Versuche dies:

is_var_defined()
{
    if [ $# -ne 1 ]
    then
        echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
        exit 1
    fi
    # Tricky.  Since Bash option 'set -u' may be enabled, we cannot directly test if a variable
    # is defined with this construct: [ ! -z "$var" ].  Instead, we must use default value
    # substitution with this construct: [ ! -z "${var:-}" ].  Normally, a default value follows the
    # operator ':-', but here we leave it blank for empty (null) string.  Finally, we need to
    # substitute the text from $1 as 'var'.  This is not allowed directly in Bash with this
    # construct: [ ! -z "${$1:-}" ].  We need to use indirection with eval operator.
    # Example: $1="var"
    # Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]"
    # Code  execute: [ ! -z ${var:-} ]
    eval "[ ! -z \${$1:-} ]"
    return $?  # Pedantic.
}

Related: Wie prüfe ich in Bash, ob eine Variable im "-u" -Modus definiert ist


Du kannst tun:

function a {
        if [ ! -z "$1" ]; then
                echo '$1 is set'
        fi
}

Für diejenigen, die in einem Skript mit set -u nach unset oder empty suchen set -u :

if [ -z "${var-}" ]; then
   echo "Must provide var environment variable. Exiting...."
   exit 1
fi

Die reguläre [ -z "$var" ] Prüfung wird mit var; unbound variable fehlschlagen var; unbound variable [ -z "${var-}" ] var; unbound variable wenn ' set -u aber [ -z "${var-}" ] zu einer leeren Zeichenfolge expands , wenn var ist, ohne zu scheitern.


Ich benutze immer dieses, basierend auf der Tatsache, dass es leicht für jemanden zu verstehen ist, der den Code zum ersten Mal sieht:

if [ "$variable" = "" ]
    then
    echo "Variable X is empty"
fi

Und, wenn Sie überprüfen möchten, ob nicht leer;

if [ ! "$variable" = "" ]
    then
    echo "Variable X is not empty"
fi

Das ist es.


Ich habe einen (viel) besseren Code dafür gefunden, wenn Sie nach etwas in [email protected] suchen möchten.

if [[ $1 = "" ]]
then
  echo '$1 is blank'
else
  echo '$1 is filled up'
fi

Warum das alles? Alles in [email protected] existiert in Bash, aber standardmäßig ist es leer, also können test -z und test -n Ihnen nicht helfen.

Update: Sie können auch die Anzahl der Zeichen in einem Parameter zählen.

if [ ${#1} = 0 ]
then
  echo '$1 is blank'
else
  echo '$1 is filled up'
fi

In bash können Sie -v innerhalb des [[ ]] Builtins verwenden:

#! /bin/bash -u

if [[ ! -v SOMEVAR ]]; then
    SOMEVAR='hello'
fi

echo $SOMEVAR

Lesen Sie den Abschnitt "Parametererweiterung" der bash Manpage. Die Parametererweiterung bietet keinen allgemeinen Test für eine Variable, die gesetzt wird, aber es gibt verschiedene Dinge, die Sie mit einem Parameter tun können, wenn er nicht gesetzt ist.

Beispielsweise:

function a {
    first_arg=${1-foo}
    # rest of the function
}

wird first_arg gleich $1 wenn es zugewiesen ist, ansonsten verwendet es den Wert "foo". Wenn absolut ein einzelner Parameter benötigt wird und kein guter Standard vorhanden ist, können Sie mit einer Fehlermeldung beenden, wenn kein Parameter angegeben ist:

function a {
    : ${1?a must take a single argument}
    # rest of the function
}

(Beachten Sie die Verwendung von : als Null-Befehl, der nur die Werte seiner Argumente erweitert. Wir wollen nichts mit $1 in diesem Beispiel tun, nur beenden, wenn es nicht gesetzt ist)


Mein bevorzugter Weg ist dies:

$var=10
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$unset var
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set

Wenn also eine Variable gesetzt ist, wird sie "eine Negation des resultierenden false " (was true = "ist gesetzt").

Und wenn es nicht gesetzt ist, wird es "eine Negation des resultierenden true " (wie das leere Ergebnis als true auswertet) (wird also als false = "NICHT gesetzt" enden).


Um nach Zeichenkettenvariablen zu suchen, die nicht null oder nicht null sind, dh wenn sie gesetzt sind, verwenden Sie

if [ -n "$1" ]

Es ist das Gegenteil von -z . Ich benutze -n mehr als -z .


Um zu überprüfen, ob eine Variable mit einem nicht leeren Wert belegt ist, verwenden Sie [ -n "$x" ] , wie andere bereits angegeben haben.

In den meisten Fällen ist es eine gute Idee, eine Variable mit einem leeren Wert genauso zu behandeln wie eine Variable, die nicht gesetzt ist. Sie können die beiden jedoch unterscheiden, wenn Sie Folgendes benötigen: [ -n "${x+set}" ] ( "${x+set}" erweitert, wenn x ist, und auf den leeren String, wenn x ist).

Um zu überprüfen, ob ein Parameter übergeben wurde, testen Sie $# , die Anzahl der Parameter, die an die Funktion übergeben werden (oder an das Skript, wenn sie nicht in einer Funktion sind) (siehe Pauls Antwort ).


Während die meisten der hier genannten Techniken korrekt sind, unterstützt bash 4.2 einen tatsächlichen Test auf das Vorhandensein einer Variablen ( man bash ), anstatt den Wert der Variablen zu testen.

[[ -v foo ]]; echo $?
# 1

foo=bar
[[ -v foo ]]; echo $?
# 0

foo=""
[[ -v foo ]]; echo $?
# 0

Wenn var ein Array sein kann, ist die [ -z "${var+x}" ] Parameterersetzung falsch. Um wirklich sicher in Bash zu sein, müssen Sie Array-Syntax wie [ "${#var[@]}" = 0 ] , wie unten gezeigt.

is-var-set () {
    results="\${var+x}=${var+x}\t\${#var[@]}=${#var[@]}"
    if [ -z "${var+x}" ] && [ "${#var[@]}" = 0 ]; then
        echo -e "$1: var's unset.\t$results"
    elif [ -n "${var+x}" ] && [ "${#var[@]}" != 0 ]; then
        echo -e "$1: var is set. \t$results"
    else
        echo -e "$1: Is var set? \t$results"
    fi
    unset var # so we don't have to do it everywhere else
}

In fast allen Fällen stimmen sie zu. Die einzige Situation, die ich gefunden habe, wo die Array-Methode genauer ist, ist, wenn die Variable ein nicht leeres Array mit der Position 0 unset ist (zB in Test 7 und A unten). Diese Meinungsverschiedenheit kommt daher, dass $var eine Abkürzung für ${var[0]} , also überprüft [ -z "${var+x}" ] nicht das gesamte Array.

Hier sind meine Testfälle.

unset var;      is-var-set 1 # var unset
var='';         is-var-set 2 # var[0] set to ''
var=foo;        is-var-set 3 # var[0] set to 'foo'
var=();         is-var-set 4 # var unset (all indices)
var=(foo);      is-var-set 5 # var[0] set to 'foo'
var=([0]=foo);  is-var-set 6 # var[0] set to 'foo'
var=([1]=foo);  is-var-set 7 # var[0] unset, but var[1] set to 'foo'
declare -a var; is-var-set 8 # var empty, but declared as an array
declare -A var; is-var-set 9 # var empty, but declared as an associative array
declare -A var  # Because is-var-set() conveniently unsets it
var=([xz]=foo); is-var-set A # var[xz] set to 'foo', but var's otherwise empty
declare -a var  # Demonstrate that Bash knows about var, even when there's
declare -A var; is-var-set B # apparently no way to just _check_ its existence

Hier ist die Ausgabe.

1: var's unset. ${var+x}=       ${#var[@]}=0
2: var is set.  ${var+x}=x      ${#var[@]}=1
3: var is set.  ${var+x}=x      ${#var[@]}=1
4: var's unset. ${var+x}=       ${#var[@]}=0
5: var is set.  ${var+x}=x      ${#var[@]}=1
6: var is set.  ${var+x}=x      ${#var[@]}=1
7: Is var set?  ${var+x}=       ${#var[@]}=1
8: var's unset. ${var+x}=       ${#var[@]}=0
9: var's unset. ${var+x}=       ${#var[@]}=0
A: Is var set?  ${var+x}=       ${#var[@]}=1
./foo.sh: line 26: declare: var: cannot convert indexed to associative array
B: var's unset. ${var+x}=       ${#var[@]}=0

In Summe:

  • ${var+x} Erweiterung der Syntax von ${var+x} -Parametern funktioniert in den meisten Fällen genauso gut wie die Array-Syntax ${#var[@]} , z. B. die Überprüfung von Parametern auf Funktionen. Der einzige Fall, in dem dieser Fall zu Bruch gehen könnte, ist, wenn eine zukünftige Version von Bash eine Möglichkeit bietet, Arrays an Funktionen zu übergeben, ohne Inhalte in einzelne Argumente zu konvertieren.
  • Array-Syntax ist für nicht leere Arrays (assoziativ oder nicht) mit Element 0 unset erforderlich.
  • Neither syntax explains what's going on if declare -a var has been used without assigning even a null value somewhere in the array. Bash still distinguishes the case somewhere (as seen in test B above), so this answer's not foolproof. Fortunately Bash converts exported environment variables into strings when running a program/script, so any issues with declared-but-unset variables will be contained to a single script, at least if it's not sourcing other scripts.

If you wish to test that a variable is bound or unbound, this works well, even after you've turned on the nounset option:

set -o noun set

if printenv variableName >/dev/null; then
    # variable is bound to a value
else
    # variable is unbound
fi

[[ $foo ]]

Oder

(( ${#foo} ))

Oder

let ${#foo}

Oder

declare -p foo

if [ "$1" != "" ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi

Für Argumente ist es normalerweise besser, $ # zu testen, was meiner Meinung nach die Anzahl der Argumente ist.

if [ $# -gt 0 ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi

if [[ ${!xx[@]} ]] ; then echo xx is defined; fi






variables