Wie überprüfe ich, ob eine Variable in Bash gesetzt ist?

1567

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

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

function a {
    # if $1 is set ?
}
prosseek
quelle
12
if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi.
Jens
210
Hinweis für Lösungssuchende: Es gibt viele hoch bewertete Antworten auf diese Frage, die die Frage "ist nicht leer" beantworten. Die mehr Korrekturlösungen ("is variable set") werden in den Antworten von Jens und Lionel unten erwähnt.
Nathan Kidd
8
Auch Russell Harmon und Seamus sind mit ihrem -vTest korrekt , obwohl dies anscheinend nur für neue Versionen von verfügbar ist bashund nicht über Shells hinweg tragbar ist.
Graeme
5
Wie von @NathanKidd hervorgehoben, geben Lionel und Jens die richtigen Lösungen. prosseek, du solltest deine akzeptierte Antwort auf eine dieser Antworten umstellen .
Garrett
3
... oder die falsche Antwort könnte von den anspruchsvolleren unter uns abgelehnt werden, da @prosseek das Problem nicht anspricht.
Dan3

Antworten:

2303

(Normalerweise) Der richtige Weg

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

Dabei ${var+x}handelt es sich um eine Parametererweiterung, die nichts varergibt, wenn sie nicht gesetzt ist, und die Zeichenfolge xansonsten ersetzt.

Zitate Exkurs

Anführungszeichen können weggelassen werden (so können wir ${var+x}stattdessen sagen "${var+x}"), da diese Syntax und Verwendung garantiert, dass dies nur zu etwas erweitert wird, für das keine Anführungszeichen erforderlich sind (da es entweder zu erweitert wird x(das keine Wortumbrüche enthält und daher keine Anführungszeichen benötigt) oder zu nichts (was dazu führt [ -z ], was bequemerweise den gleichen Wert (wahr) [ -z "" ]ergibt , der auch der Fall ist)).

Obwohl Anführungszeichen sicher weggelassen werden können und es nicht für alle sofort offensichtlich war (es war nicht einmal für den Erstautor dieser Anführungszeichenerklärung offensichtlich, der auch ein wichtiger Bash-Codierer ist), wäre es manchmal besser, die Lösung zu schreiben mit Anführungszeichen als [ -z "${var+x}" ], zu den sehr geringen möglichen Kosten einer O (1) -Geschwindigkeitsstrafe. Der Erstautor fügte dies auch als Kommentar neben dem Code hinzu, indem er diese Lösung verwendete und die URL zu dieser Antwort angab, die nun auch die Erklärung enthält, warum die Anführungszeichen sicher weggelassen werden können.

(Oft) Der falsche Weg

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

Dies ist häufig falsch, da nicht zwischen einer nicht gesetzten Variablen und einer auf die leere Zeichenfolge gesetzten Variablen unterschieden wird. Das heißt, wenn var='', dann gibt die obige Lösung "var is blank" aus.

Die Unterscheidung zwischen nicht gesetzt und "auf die leere Zeichenfolge setzen" ist 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 angeben, während die Angabe der leeren Zeichenfolge dies tun sollte Lassen Sie das Skript eine leere Erweiterung oder Liste zusätzlicher Eigenschaften verwenden.

Die Unterscheidung ist jedoch möglicherweise nicht in jedem Szenario wesentlich. In diesen Fällen [ -z "$var" ]wird alles in Ordnung sein.

Lionel
quelle
29
@ Garrett, Ihre Bearbeitung hat diese Antwort falsch gemacht, ${var+x}ist die richtige Substitution zu verwenden. Die Verwendung [ -z ${var:+x} ]erzeugt kein anderes Ergebnis als [ -z "$var" ].
Graeme
11
Das funktioniert nicht. Ich erhalte "nicht gesetzt", unabhängig davon, ob var auf einen Wert gesetzt ist oder nicht (gelöscht mit "unset var", "echo $ var" erzeugt keine Ausgabe).
Brent212
10
Für die Syntax der Lösung $ {parameter + word} lautet der offizielle Handbuchabschnitt gnu.org/software/bash/manual/… ; Ein Fehler darin ist jedoch, dass diese Syntax nicht sehr deutlich erwähnt wird, sondern nur ein Anführungszeichen angegeben wird (das Weglassen des Doppelpunkts [":"] führt zu einem Test nur für einen Parameter, der nicht gesetzt ist. $ {parameter: + word} [bedeutet] Wenn der Parameter null oder nicht gesetzt ist, wird nichts ersetzt, andernfalls wird die Erweiterung des Wortes ersetzt.); Die zitierte Referenz pubs.opengroup.org/onlinepubs/9699919799/utilities/… (gut zu wissen) enthält hier viel klarere Dokumente.
Destiny Architect
7
Es sieht aus wie Anführungszeichen sind erforderlich, wenn Sie mehrere Ausdrücke verwendet werden , zB [ -z "" -a -z ${var+x} ]wird bash: [: argument expectedin bash 4.3-ubuntu (aber nicht zB zsh). Ich mag die Antwort mit einer Syntax, die in einigen Fällen funktioniert, wirklich nicht.
FauxFaux
41
Die Verwendung eines einfachen [ -z $var ]ist nicht "falscher" als das Weglassen von Anführungszeichen. In beiden Fällen machen Sie Annahmen über Ihre Eingabe. Wenn Sie eine leere Zeichenfolge als nicht gesetzt behandeln möchten, [ -z $var ]ist dies alles, was Sie benötigen.
Nshew
909

Verwenden Sie diese Option, um nach Zeichenfolgenvariablen ungleich Null / ungleich Null zu suchen

if [ -n "$1" ]

Es ist das Gegenteil von -z. Ich benutze -nmehr als -z.

Sie würden es wie folgt verwenden:

if [ -n "$1" ]; then
  echo "You supplied the first parameter!"
else
  echo "First parameter not supplied."
fi
mbrannig
quelle
86
Normalerweise ziehe ich es [[ ]]vor [ ], da [[ ]]es leistungsfähiger ist und in bestimmten Situationen weniger Probleme verursacht (siehe diese Frage für eine Erklärung des Unterschieds zwischen den beiden). Die Frage fragt speziell nach einer Bash- Lösung und erwähnt keine Portabilitätsanforderungen.
Flow
18
Die Frage ist, wie man sehen kann, ob eine Variable gesetzt ist . Dann nehme an, Sie können nicht , dass die Variable ist gesetzt.
HelloGoodbye
7
Ich stimme zu, []funktioniert besser, insbesondere für Shell-Skripte (ohne Bash).
Hengjie
73
Schlägt weiter set -u.
Ciro Santilli 法轮功 病毒 审查. 事件 法轮功
63
Beachten Sie, dass dies -nder Standardtest ist, also einfacher [ "$1" ]oder auch besser [[ $1 ]]. Beachten Sie auch, dass das [[ ]] Zitieren nicht erforderlich ist .
Der
478

So testen Sie, ob ein Parameter nicht gesetzt oder leer ("Null") oder mit einem Wert gesetzt ist :

+--------------------+----------------------+-----------------+-----------------+
|   Expression       |       parameter      |     parameter   |    parameter    |
|   in script:       |   Set and Not Null   |   Set But Null  |      Unset      |
+--------------------+----------------------+-----------------+-----------------+
| ${parameter:-word} | substitute parameter | substitute word | substitute word |
| ${parameter-word}  | substitute parameter | substitute null | substitute word |
| ${parameter:=word} | substitute parameter | assign word     | assign word     |
| ${parameter=word}  | substitute parameter | substitute null | assign word     |
| ${parameter:?word} | substitute parameter | error, exit     | error, exit     |
| ${parameter?word}  | substitute parameter | substitute null | error, exit     |
| ${parameter:+word} | substitute word      | substitute null | substitute null |
| ${parameter+word}  | substitute word      | substitute word | substitute null |
+--------------------+----------------------+-----------------+-----------------+

Quelle: POSIX: Parametererweiterung :

In allen mit "Ersatz" angezeigten Fällen wird der Ausdruck durch den angezeigten Wert ersetzt. In allen mit "Zuweisen" angezeigten Fällen wird dem Parameter dieser Wert zugewiesen, der auch den Ausdruck ersetzt.

Um dies in Aktion zu zeigen:

+--------------------+----------------------+-----------------+-----------------+
|   Expression       |  FOO="world"         |     FOO=""      |    unset FOO    |
|   in script:       |  (Set and Not Null)  |  (Set But Null) |     (Unset)     |
+--------------------+----------------------+-----------------+-----------------+
| ${FOO:-hello}      | world                | hello           | hello           |
| ${FOO-hello}       | world                | ""              | hello           |
| ${FOO:=hello}      | world                | FOO=hello       | FOO=hello       |
| ${FOO=hello}       | world                | ""              | FOO=hello       |
| ${FOO:?hello}      | world                | error, exit     | error, exit     |
| ${FOO?hello}       | world                | ""              | error, exit     |
| ${FOO:+hello}      | hello                | ""              | ""              |
| ${FOO+hello}       | hello                | hello           | ""              |
+--------------------+----------------------+-----------------+-----------------+
Jens
quelle
5
@HelloGoodbye Ja, es funktioniert: set foo; echo ${1:-set but null or unset}Echos "foo"; set --; echo ${1:-set but null or unset}Echos gesetzt, aber null ...
Jens
4
@HelloGoodbye Die Positionsparameter können eingestellt werden mit set:-)
Jens
95
Diese Antwort ist sehr verwirrend. Gibt es praktische Beispiele für die Verwendung dieser Tabelle?
Ben Davis
12
@BenDavis Die Details werden im Link zum POSIX-Standard erläutert, der auf das Kapitel verweist, aus dem die Tabelle stammt. Ein Konstrukt, das ich in fast jedem Skript verwende, das ich schreibe, besteht : ${FOOBAR:=/etc/foobar.conf}darin, einen Standardwert für eine Variable festzulegen, wenn diese nicht gesetzt oder null ist.
Jens
1
parameterist ein beliebiger Variablenname. wordist eine Zeichenfolge, die ersetzt werden muss, je nachdem, welche Syntax in der Tabelle Sie verwenden und ob die Variable $parametergesetzt, gesetzt, aber null oder nicht gesetzt ist. Nicht um die Dinge komplizierter zu machen, sondern wordkann auch Variablen enthalten! Dies kann sehr nützlich sein, um optionale Argumente zu übergeben, die durch ein Zeichen getrennt sind. Beispiel: ${parameter:+,${parameter}}Gibt ein Komma getrennt aus, ,$parameterwenn es gesetzt, aber nicht null ist. In diesem Fall wordist,${parameter}
TrinitronX
260

Während die meisten der hier angegebenen 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

Insbesondere verursacht dieser Ansatz keinen Fehler, wenn nach einer nicht gesetzten Variablen in gesucht wird set -uset -o nounset Gegensatz zu vielen anderen Ansätzen, wie z. B. der Verwendung, / mode[ -z .

Russell Harmon
quelle
9
In Bash 4.1.2, unabhängig davon, ob eine Variable gesetzt ist, [[ -v aaa ]]; echo $?==>-bash: conditional binary operator expected -bash: syntax error near 'aaa'
Dan
32
Das Argument '-v' zum eingebauten 'Test' wurde in Bash 4.2 hinzugefügt.
Ti Strga
19
Das Argument -v wurde als Ergänzung zur Shell-Option -u (Nomenmenge) hinzugefügt. Wenn 'nounset' aktiviert ist (set -u), gibt die Shell einen Fehler zurück und wird beendet, wenn sie nicht interaktiv ist. $ # war gut für die Überprüfung der Positionsparameter. Benannte Variablen mussten jedoch anders als mit Clobbering als nicht gesetzt identifiziert werden. Es ist bedauerlich, dass diese Funktion so spät verfügbar ist, da viele zwangsläufig mit früheren Versionen kompatibel sind. In diesem Fall können sie sie nicht verwenden. Die einzige andere Möglichkeit besteht darin, Tricks oder "Hacks" zu verwenden, um das Problem zu umgehen, wie oben gezeigt, aber es ist am unelegantesten.
Osirisgothra
2
Beachten Sie, dass dies nicht für Variablen funktioniert, die deklariert, aber nicht gesetzt sind. zBdeclare -a foo
miken32
17
Deshalb lese ich nach der akzeptierten / am höchsten bewerteten Antwort weiter.
Joe
176

Es gibt viele Möglichkeiten, dies zu tun, wobei die folgenden eine davon sind:

if [ -z "$1" ]

Dies ist erfolgreich, wenn $ 1 null oder nicht gesetzt ist

ennuikiller
quelle
46
Es gibt einen Unterschied zwischen einem nicht gesetzten Parameter und einem Parameter mit einem Nullwert.
Chepper
21
Ich möchte nur pedantisch sein und darauf hinweisen, dass dies die entgegengesetzte Antwort auf die Frage ist. In den Fragen wird gefragt, ob die Variable gesetzt ist, nicht, ob die Variable nicht gesetzt ist.
Philluminati
47
[[ ]]ist nichts anderes als eine Portabilitätsfalle. if [ -n "$1" ]sollte hier verwendet werden.
Jens
73
Diese Antwort ist falsch. In der Frage wird nach einer Möglichkeit gefragt, festzustellen, ob eine Variable festgelegt ist und nicht, ob sie auf einen nicht leeren Wert festgelegt ist. Gegeben foo="", $foohat einen Wert, -zmeldet aber lediglich, dass er leer ist. Und -z $foowird explodieren, wenn Sie haben set -o nounset.
Keith Thompson
4
Dies hängt von der Definition von "Variable ist gesetzt" ab. Wenn Sie überprüfen möchten, ob die Variable auf eine Zeichenfolge ungleich Null festgelegt ist , ist die mbranning-Antwort korrekt. Wenn Sie jedoch überprüfen möchten, ob die Variable deklariert, aber nicht initialisiert ist (dh foo=), ist Russels Antwort korrekt.
Flow
77

Ich finde die POSIX-Tabelle in der anderen Antwort immer langsam, also hier meine Meinung dazu:

   +----------------------+------------+-----------------------+-----------------------+
   |   if VARIABLE is:    |    set     |         empty         |        unset          |
   +----------------------+------------+-----------------------+-----------------------+
 - |  ${VARIABLE-default} | $VARIABLE  |          ""           |       "default"       |
 = |  ${VARIABLE=default} | $VARIABLE  |          ""           | $(VARIABLE="default") |
 ? |  ${VARIABLE?default} | $VARIABLE  |          ""           |       exit 127        |
 + |  ${VARIABLE+default} | "default"  |       "default"       |          ""           |
   +----------------------+------------+-----------------------+-----------------------+
:- | ${VARIABLE:-default} | $VARIABLE  |       "default"       |       "default"       |
:= | ${VARIABLE:=default} | $VARIABLE  | $(VARIABLE="default") | $(VARIABLE="default") |
:? | ${VARIABLE:?default} | $VARIABLE  |       exit 127        |       exit 127        |
:+ | ${VARIABLE:+default} | "default"  |          ""           |          ""           |
   +----------------------+------------+-----------------------+-----------------------+

Beachten Sie, dass jede Gruppe (mit und ohne vorangestelltem Doppelpunkt) dieselben festgelegten und nicht festgelegten Fälle hat. Das einzige, was sich unterscheidet, ist die Behandlung der leeren Fälle.

Mit dem vorhergehenden Doppelpunkt sind die leeren und nicht gesetzten Fälle identisch, daher würde ich diese nach Möglichkeit verwenden (dh :=nicht nur =, weil der leere Fall inkonsistent ist).

Überschriften:

  • set means VARIABLEist nicht leer ( VARIABLE="something")
  • leer bedeutet VARIABLEleer / null ( VARIABLE="")
  • nicht gesetzte Mittel VARIABLEexistieren nicht ( unset VARIABLE)

Werte:

  • $VARIABLE bedeutet, dass das Ergebnis der ursprüngliche Wert der Variablen ist.
  • "default" bedeutet, dass das Ergebnis die bereitgestellte Ersatzzeichenfolge war.
  • "" bedeutet, dass das Ergebnis null ist (eine leere Zeichenfolge).
  • exit 127 bedeutet, dass das Skript mit dem Exit-Code 127 nicht mehr ausgeführt wird.
  • $(VARIABLE="default")bedeutet, dass das Ergebnis der ursprüngliche Wert der Variablen ist und die bereitgestellte Ersatzzeichenfolge der Variablen für die zukünftige Verwendung zugewiesen wird.
deizel
quelle
1
Sie haben nur diejenigen behoben, bei denen es sich um tatsächliche Codierungsfehler handelt (Fälle unerwünschter Indirektion bei der Arbeit mit Variablen). Ich habe eine Änderung vorgenommen, um einige weitere Fälle zu beheben, in denen der Dollar bei der Interpretation der Beschreibung einen Unterschied macht. Übrigens sind alle Shell-Variablen (mit Ausnahme von Arrays) String-Variablen. Es kann einfach vorkommen, dass sie eine Zeichenfolge enthalten, die als Zahl interpretiert werden kann. Wenn Sie über Zeichenfolgen sprechen, wird die Nachricht nur beschlagen. Anführungszeichen haben nichts mit Zeichenfolgen zu tun, sie sind nur eine Alternative zum Entkommen. VARIABLE=""könnte geschrieben werden als VARIABLE=. Ersteres ist jedoch besser lesbar.
Palec
Vielen Dank für die Tabelle, es ist sehr nützlich, aber ich versuche, das Skript zu beenden, wenn es nicht gesetzt oder leer ist. Aber der Exit-Code, den ich bekomme, ist 1, nicht 127.
Astronaut
64

Um zu sehen, ob eine Variable nicht leer ist, verwende ich

if [[ $var ]]; then ...       # `$var' expands to a nonempty string

Das Gegenteil testet, ob eine Variable entweder nicht gesetzt oder leer ist:

if [[ ! $var ]]; then ...     # `$var' expands to the empty string (set or not)

Um zu sehen, ob eine Variable gesetzt ist (leer oder nicht leer), verwende ich

if [[ ${var+x} ]]; then ...   # `var' exists (empty or nonempty)
if [[ ${1+x} ]]; then ...     # Parameter 1 exists (empty or nonempty)

Das Gegenteil testet, ob eine Variable nicht gesetzt ist:

if [[ ! ${var+x} ]]; then ... # `var' is not set at all
if [[ ! ${1+x} ]]; then ...   # We were called with no arguments
Phkoester
quelle
Ich benutze das auch schon eine Weile; nur in reduzierter Weise:[ $isMac ] && param="--enable-shared"
@ Bhaskar Ich denke, das liegt daran, dass diese Antwort bereits fast ein halbes Jahr zuvor im Wesentlichen dieselbe Antwort lieferte (verwenden Sie ${variable+x}, um xiff zu erhalten $variable). Außerdem enthält es viel detailliertere Erklärungen, warum es richtig ist.
Mark Haferkamp
aber ${variable+x}ist weniger lesbar (& offensichtlich)
knocte
35

Bei einer modernen Version von Bash (4.2 oder höher, glaube ich; ich weiß es nicht genau) 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
Seamus Connor
quelle
5
Beachten Sie auch, dass dies [ -v "$VARNAME" ]nicht falsch ist, sondern einfach einen anderen Test durchführt. Nehmen wir an VARNAME=foo; Dann wird geprüft, ob eine Variable mit dem Namen foogesetzt ist.
Chepper
5
Hinweis für diejenigen, die Portabilität -v
wünschen
Wenn man bekommt [: -v: unexpected operator, muss man sicherstellen, bashstatt zu verwenden sh.
Koppor
25
if [ "$1" != "" ]; then
  echo \$1 is set
else
  echo \$1 is not set
fi

Obwohl es für Argumente normalerweise am besten ist, $ # 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
Paul Creasey
quelle
1
Der erste Test ist rückwärts; Ich denke du willst [ "$1" != "" ](oder [ -n "$1" ]) ...
Gordon Davisson
10
Dies schlägt fehl, wenn $1die leere Zeichenfolge festgelegt ist.
Hallo Goodbye
2
Der zweite Teil der Antwort (Zählparameter) ist eine nützliche Problemumgehung für den ersten Teil der Antwort, der nicht funktioniert, wenn $1eine leere Zeichenfolge festgelegt ist.
Mark Berry
Dies schlägt fehl, wenn set -o nounsetes aktiviert ist.
Flimm
21

Hinweis

Ich gebe aufgrund des bashTags eine stark auf Bash ausgerichtete Antwort .

Kurze Antwort

Solange Sie nur mit benannten Variablen in Bash arbeiten, sollte diese Funktion Ihnen immer mitteilen, ob die Variable festgelegt wurde, auch wenn es sich um ein leeres Array handelt.

variable-is-set() {
    declare -p "$1" &>/dev/null
}

Warum das so ist

Wenn vares sich bei Bash (mindestens bis 3.0) um eine deklarierte / gesetzte Variable handelt, wird declare -p varein declareBefehl ausgegeben , der die Variable varauf den aktuellen Typ und Wert setzt und den Statuscode 0(Erfolg) zurückgibt . Wenn varnicht deklariert ist, wird declare -p vareine Fehlermeldung an den stderrStatuscode ausgegeben und dieser zurückgegeben 1. Leitet mit &>/dev/nullund leitet sowohl regulär stdoutals auch stderrAusgabe an um/dev/null , wird nie gesehen und ohne den Statuscode zu ändern. Somit gibt die Funktion nur den Statuscode zurück.

Warum andere Methoden (manchmal) in Bash fehlschlagen

  • [ -n "$var" ]: Dies prüft nur, ob ${var[0]}es nicht leer ist. (In Bash $varist das gleiche wie ${var[0]}.)
  • [ -n "${var+x}" ]: Dies prüft nur, ob ${var[0]}gesetzt ist.
  • [ "${#var[@]}" != 0 ]: Dies prüft nur, ob mindestens ein Index von $vargesetzt ist.

Wenn diese Methode in Bash fehlschlägt

Dies funktioniert nur bei benannten Variablen (einschließlich $_), nicht bestimmten Sondergrößen ( $!, $@, $#, $$, $*, $?, $-, $0, $1, $2, ... und alle , die ich vergessen habe). Da es sich bei keinem dieser Arrays um Arrays handelt, [ -n "${var+x}" ]funktioniert der POSIX-Stil für alle diese speziellen Variablen. Achten Sie jedoch darauf, dass Sie es nicht in eine Funktion einschließen, da viele spezielle Variablen beim Aufrufen von Funktionen Werte / Existenz ändern.

Hinweis zur Shell-Kompatibilität

Wenn Ihr Skript Arrays enthält und Sie versuchen, es mit so vielen Shells wie möglich kompatibel zu machen, sollten Sie die Verwendung von typeset -panstelle von in Betracht ziehen declare -p. Ich habe gelesen, dass ksh nur das erstere unterstützt, konnte dies aber nicht testen. Ich weiß, dass Bash 3.0+ und Zsh 5.5.1 beide unterstützen typeset -pund declare -psich nur dadurch unterscheiden, dass eines eine Alternative für das andere ist. Aber ich habe keine Unterschiede über diese beiden Schlüsselwörter hinaus getestet, und ich habe keine anderen Shells getestet.

Wenn Ihr Skript POSIX sh-kompatibel sein soll, können Sie keine Arrays verwenden. Ohne Arrays [ -n "{$var+x}" ]funktioniert.

Vergleichscode für verschiedene Methoden in Bash

Diese Funktion deaktiviert die Variable var, evals den übergebenen Code, führt Tests aus, um festzustellen, ob varder evald-Code festgelegt ist, und zeigt schließlich die resultierenden Statuscodes für die verschiedenen Tests an.

Ich Skipping test -v var, [ -v var ]und [[ -v var ]]weil sie identische Ergebnisse an den POSIX - Standard ergeben [ -n "${var+x}" ], während erfordern Bash 4.2+. Ich überspringe auch, typeset -pweil es das gleiche ist wie declare -pin den Shells, die ich getestet habe (Bash 3.0 bis 5.0 und Zsh 5.5.1).

is-var-set-after() {
    # Set var by passed expression.
    unset var
    eval "$1"

    # Run the tests, in increasing order of accuracy.
    [ -n "$var" ] # (index 0 of) var is nonempty
    nonempty=$?
    [ -n "${var+x}" ] # (index 0 of) var is set, maybe empty
    plus=$?
    [ "${#var[@]}" != 0 ] # var has at least one index set, maybe empty
    count=$?
    declare -p var &>/dev/null # var has been declared (any type)
    declared=$?

    # Show test results.
    printf '%30s: %2s %2s %2s %2s\n' "$1" $nonempty $plus $count $declared
}

Testfallcode

Beachten Sie, dass Testergebnisse unerwartet sein können, da Bash nicht numerische Array-Indizes als "0" behandelt, wenn die Variable nicht als assoziatives Array deklariert wurde. Außerdem sind assoziative Arrays nur in Bash 4.0+ gültig.

# Header.
printf '%30s: %2s %2s %2s %2s\n' "test" '-n' '+x' '#@' '-p'
# First 5 tests: Equivalent to setting 'var=foo' because index 0 of an
# indexed array is also the nonindexed value, and non-numerical
# indices in an array not declared as associative are the same as
# index 0.
is-var-set-after "var=foo"                        #  0  0  0  0
is-var-set-after "var=(foo)"                      #  0  0  0  0
is-var-set-after "var=([0]=foo)"                  #  0  0  0  0
is-var-set-after "var=([x]=foo)"                  #  0  0  0  0
is-var-set-after "var=([y]=bar [x]=foo)"          #  0  0  0  0
# '[ -n "$var" ]' fails when var is empty.
is-var-set-after "var=''"                         #  1  0  0  0
is-var-set-after "var=([0]='')"                   #  1  0  0  0
# Indices other than 0 are not detected by '[ -n "$var" ]' or by
# '[ -n "${var+x}" ]'.
is-var-set-after "var=([1]='')"                   #  1  1  0  0
is-var-set-after "var=([1]=foo)"                  #  1  1  0  0
is-var-set-after "declare -A var; var=([x]=foo)"  #  1  1  0  0
# Empty arrays are only detected by 'declare -p'.
is-var-set-after "var=()"                         #  1  1  1  0
is-var-set-after "declare -a var"                 #  1  1  1  0
is-var-set-after "declare -A var"                 #  1  1  1  0
# If 'var' is unset, then it even fails the 'declare -p var' test.
is-var-set-after "unset var"                      #  1  1  1  1

Testausgabe

Die Test Mnemonik in der Kopfzeile entsprechen [ -n "$var" ], [ -n "${var+x}" ], [ "${#var[@]}" != 0 ], und declare -p varist.

                         test: -n +x #@ -p
                      var=foo:  0  0  0  0
                    var=(foo):  0  0  0  0
                var=([0]=foo):  0  0  0  0
                var=([x]=foo):  0  0  0  0
        var=([y]=bar [x]=foo):  0  0  0  0
                       var='':  1  0  0  0
                 var=([0]=''):  1  0  0  0
                 var=([1]=''):  1  1  0  0
                var=([1]=foo):  1  1  0  0
declare -A var; var=([x]=foo):  1  1  0  0
                       var=():  1  1  1  0
               declare -a var:  1  1  1  0
               declare -A var:  1  1  1  0
                    unset var:  1  1  1  1

Zusammenfassung

  • declare -p var &>/dev/null ist (100%?) zuverlässig für das Testen benannter Variablen in Bash seit mindestens 3.0.
  • [ -n "${var+x}" ] ist in POSIX-kompatiblen Situationen zuverlässig, kann jedoch keine Arrays verarbeiten.
  • Es gibt andere Tests zum Überprüfen, ob eine Variable nicht leer ist, und zum Überprüfen auf deklarierte Variablen in anderen Shells. Diese Tests eignen sich jedoch weder für Bash- noch für POSIX-Skripte.
Mark Haferkamp
quelle
3
Von den Antworten, die ich versucht habe, ist diese ( declare -p var &>/dev/null) die EINZIGE, die funktioniert. VIELEN DANK!
user1387866
2
@ mark-haferkamp Ich habe versucht, Ihre Antwort zu bearbeiten, um das kritische vorangestellte "/" zu Ihrem Funktionscode hinzuzufügen, damit er lautet, ... &> /dev/nullaber SO würde mich nicht ein einzelnes Zeichen bearbeiten lassen 🙄 (muss> 6 Zeichen sein - habe sogar versucht, Leerzeichen hinzuzufügen aber es hat nicht funktioniert). Es könnte sich auch lohnen, die Funktion zu ändern, um $1für ein Beispiel mit dem Namen Variable (z. B. OUTPUT_DIR) auszuschalten, da, wie Sie bereits betont haben, spezielle Variablen wie $1hier nicht funktionieren. Auf jeden Fall ist es eine kritische Änderung, andernfalls versucht der Code, eine Datei zu erstellen, die nullin einem relativen Verzeichnis namens aufgerufen wird dev. Übrigens - tolle Antwort!
Joehanna
Die Verwendung des Namens der Variablen ohne das Präfix $ funktioniert ebenfalls: Gibt declare -p PATH &> /dev/null0 declare -p ASDFASDGFASKDF &> /dev/nullzurück, wobei 1 zurückgegeben wird (bei Bash 5.0.11 (1) -Veröffentlichung)
Joehanna
1
Gute Arbeit! 1 Wort der Vorsicht: declare vardeklariert var als Variable, setzt es aber nicht in Bezug auf set -o nounset: Test mitdeclare foo bar=; set -o nounset; echo $bar; echo $foo
xebeche
@joehanna Danke, dass du das Vermisste erwischt hast /! Ich habe das behoben, aber ich denke, die Logik ist verwirrend genug, um eine Funktion zu rechtfertigen, insbesondere angesichts des Kommentars von @ xebeche. @xebeche Das ist unpraktisch für meine Antwort.… Es sieht so aus, als müsste ich etwas wie declare -p "$1" | grep =oder ausprobieren test -v "$1".
Mark Haferkamp
19

Für diejenigen , die für ungesetzt zu überprüfen suchen oder leeren , wenn sie in einem Skript mit set -u:

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

Die reguläre [ -z "$var" ]Prüfung schlägt mit var; unbound variableif fehl, wird set -ujedoch zu einer leeren Zeichenfolge [ -z "${var-}" ] erweitert , wenn sie varnicht fehlgeschlagen ist.

RubenLaguna
quelle
Ihnen fehlt ein Doppelpunkt. Es sollte ${var:-}nicht sein ${var-}. Aber in Bash kann ich bestätigen, dass es auch ohne Doppelpunkt funktioniert.
Palec
3
${var:-}und ${var-}verschiedene Dinge bedeuten. ${var:-}wird auf leere Zeichenfolge erweitert, wenn varnicht gesetzt oder null, und ${var-}wird nur dann auf leere Zeichenfolge erweitert, wenn nicht gesetzt.
RubenLaguna
Ich habe gerade etwas Neues gelernt, danke! Das Weglassen des Doppelpunkts führt zu einem Test nur für einen Parameter, der nicht festgelegt ist. Anders ausgedrückt, wenn der Doppelpunkt enthalten ist, prüft der Operator, ob beide Parameter vorhanden sind und ob ihr Wert nicht null ist. Wenn der Doppelpunkt weggelassen wird, prüft der Bediener nur die Existenz. Hier macht es keinen Unterschied, aber gut zu wissen.
Palec
17

Sie möchten beenden, wenn es nicht gesetzt ist

Das hat bei mir funktioniert. Ich wollte, dass mein Skript mit einer Fehlermeldung beendet wird, wenn kein Parameter festgelegt wurde.

#!/usr/bin/env bash

set -o errexit

# Get the value and empty validation check all in one
VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"

Dies wird mit einem Fehler zurückgegeben, wenn es ausgeführt wird

peek@peek:~$ ./setver.sh
./setver.sh: line 13: 1: You must pass a version of the format 0.0.0 as the only argument

Nur prüfen, kein Beenden - Leer und Nicht gesetzt sind UNGÜLTIG

Versuchen Sie diese Option, wenn Sie nur überprüfen möchten, ob der Wert set = VALID oder unset / empty = INVALID ist.

TSET="good val"
TEMPTY=""
unset TUNSET

if [ "${TSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID
if [ "${TUNSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID

Oder auch kurze Tests ;-)

[ "${TSET:-}"   ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY:-}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET:-}" ] && echo "VALID" || echo "INVALID"

Nur prüfen, kein Ausgang - Nur leer ist UNGÜLTIG

Und das ist die Antwort auf die Frage. Verwenden Sie diese Option, wenn Sie nur überprüfen möchten, ob der Wert set / empty = VALID oder unset = INVALID ist.

HINWEIS, die "1" in "..- 1}" ist unbedeutend, es kann alles sein (wie x)

TSET="good val"
TEMPTY=""
unset TUNSET

if [ "${TSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TUNSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID

Kurze Tests

[ "${TSET+1}"   ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY+1}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET+1}" ] && echo "VALID" || echo "INVALID"

Ich widme diese Antwort @ mklement0 (Kommentare), der mich herausforderte, die Frage genau zu beantworten.

Referenz http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02

Jarrod Chesney
quelle
15

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

In den meisten Fällen empfiehlt es sich, eine Variable mit einem leeren Wert genauso zu behandeln wie eine nicht gesetzte Variable. Sie können die beiden jedoch unterscheiden, wenn Sie Folgendes benötigen: [ -n "${x+set}" ]( "${x+set}"Erweitert auf setif xist gesetzt und auf die leere Zeichenfolge, wenn nicht gesetzt xist).

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

Gilles 'SO - hör auf böse zu sein'
quelle
14

Lesen Sie den Abschnitt "Parametererweiterung" auf der bashManpage. Die Parametererweiterung bietet keinen allgemeinen Test für eine zu setzende Variable, aber es gibt verschiedene Möglichkeiten, einen Parameter zu bearbeiten, wenn er nicht gesetzt ist.

Zum Beispiel:

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

wird first_arggleich gesetzt, $1wenn es zugewiesen ist, andernfalls wird der Wert "foo" verwendet. Wenn aunbedingt ein einzelner Parameter verwendet werden muss und kein guter Standardwert vorhanden ist, können Sie mit einer Fehlermeldung beenden, wenn kein Parameter angegeben wird:

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. $1In diesem Beispiel möchten wir nichts damit anfangen. Beenden Sie einfach, wenn er nicht festgelegt ist.)

chepner
quelle
1
Ich bin verblüfft, dass keine der anderen Antworten das Einfache und Elegante erwähnt : ${var?message}.
Tripleee
Woher hast du das genommen? Wunderbar! Es funktioniert einfach! Und es ist kurz und elegant! Vielen Dank!
Roger
13

In Bash können Sie -vinnerhalb des [[ ]]eingebauten verwenden:

#! /bin/bash -u

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

echo $SOMEVAR
AlejandroVD
quelle
8

Die Verwendung [[ -z "$var" ]]ist der einfachste Weg, um festzustellen, ob eine Variable festgelegt wurde oder nicht. -zDiese Option unterscheidet jedoch nicht zwischen einer nicht gesetzten Variablen und einer Variablen, die auf eine leere Zeichenfolge festgelegt ist:

$ set=''
$ [[ -z "$set" ]] && echo "Set" || echo "Unset" 
Unset
$ [[ -z "$unset" ]] && echo "Set" || echo "Unset"
Unset

Am besten überprüfen Sie es nach dem Variablentyp: env-Variable, Parameter oder reguläre Variable.

Für eine env-Variable:

[[ $(env | grep "varname=" | wc -l) -eq 1 ]] && echo "Set" || echo "Unset"

Für einen Parameter (zum Beispiel um die Existenz eines Parameters zu überprüfen $5):

[[ $# -ge 5 ]] && echo "Set" || echo "Unset"

Für eine reguläre Variable (mit einer Hilfsfunktion, um dies auf elegante Weise zu tun):

function declare_var {
   declare -p "$1" &> /dev/null
}
declare_var "var_name" && echo "Set" || echo "Unset"

Anmerkungen:

  • $#: gibt Ihnen die Anzahl der Positionsparameter an.
  • declare -p: gibt Ihnen die Definition der als Parameter übergebenen Variablen. Wenn vorhanden, wird 0 zurückgegeben. Wenn nicht, wird 1 zurückgegeben und eine Fehlermeldung ausgegeben.
  • &> /dev/null: Unterdrückt die Ausgabe von, declare -pohne den Rückkehrcode zu beeinflussen.
Peregring-lk
quelle
5

Die obigen Antworten funktionieren nicht, wenn die Bash-Option set -uaktiviert ist. Sie sind auch nicht dynamisch, z. B. wie wird getestet, ob eine Variable 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.
}

Verwandte Themen: Wie teste ich in Bash, ob eine Variable im Modus "-u" definiert ist?

Kevinarpe
quelle
1
Ich würde gerne so viel wissen, warum diese Antwort abgelehnt wurde ... Funktioniert hervorragend für mich.
LavaScornedOven
In Bash können Sie dasselbe auch ohne eval "[ ! -z \${$1:-} ]"Auswertung tun: Wechsel zur indirekten Bewertung : [ ! -z ${!1:-} ];.
@ BinärZebra: Interessante Idee. Ich schlage vor, Sie posten als separate Antwort.
Kevinarpe
Die Verwendung von "eval" macht diese Lösung anfällig für Code-Injection: $ is_var_defined 'x}]; Echo "gotcha"> & 2; # 'gotcha
tetsujin
4

Du kannst tun:

function a {
        if [ ! -z "$1" ]; then
                echo '$1 is set'
        fi
}
Codaddict
quelle
9
Oder Sie könnten das tun -nund nicht negieren -z.
Bis auf weiteres angehalten.
1
Sie brauchen Zitate um $1, dh , [ ! -z "$1" ]. Oder Sie können [[ ! -z $1 ]]in bash / ksh / zsh schreiben .
Gilles 'SO - hör auf böse zu sein'
5
Dies schlägt fehl, wenn $1die leere Zeichenfolge festgelegt ist.
Hallo Goodbye
4

Mein bevorzugter Weg ist folgender:

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

Wenn also eine Variable gesetzt ist, wird sie im Grunde genommen "eine Negation des Ergebnisses false" (was sein wird true= "wird gesetzt").

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

Wassermann-Kraft
quelle
1
[[ $foo ]]

Oder

(( ${#foo} ))

Oder

let ${#foo}

Oder

declare -p foo
Steven Penny
quelle
1

In einer Shell können Sie den -zOperator True verwenden, wenn die Länge der Zeichenfolge Null ist.

Ein einfacher Einzeiler zum Festlegen der Standardeinstellung, MY_VARwenn diese nicht festgelegt ist. Andernfalls können Sie optional die folgende Meldung anzeigen:

[[ -z "$MY_VAR" ]] && MY_VAR="default"
[[ -z "$MY_VAR" ]] && MY_VAR="default" || echo "Variable already set."
Kenorb
quelle
0
if [[ ${1:+isset} ]]
then echo "It was set and not null." >&2
else echo "It was not set or it was null." >&2
fi

if [[ ${1+isset} ]]
then echo "It was set but might be null." >&2
else echo "It was was not set." >&2
fi
Solidsnack
quelle
$1, $2Und bis zu $Nist immer gesetzt. Entschuldigung, das ist fehlgeschlagen.
Ich habe es versucht und es hat nicht funktioniert, vielleicht wird meine Bash-Version dafür nicht unterstützt. Idk, tut mir leid, wenn ich falsch liege. :)
0

Ich habe einen (viel) besseren Code gefunden, um dies zu tun, wenn Sie nach etwas suchen möchten $@.

if [[$ 1 = ""]]
dann
  Echo '$ 1 ist leer'
sonst
  Echo '$ 1 ist voll'
fi

Warum das alles? Alles in $@ist in Bash vorhanden, aber standardmäßig ist es leer test -zund test -nkann Ihnen nicht helfen.

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

if [$ {# 1} = 0]
dann
  Echo '$ 1 ist leer'
sonst
  Echo '$ 1 ist voll'
fi

quelle
Ich weiß, aber das war's. Wenn etwas leer ist, erhalten Sie eine Fehlermeldung! Es tut uns leid. : P
0
if [[ ${!xx[@]} ]] ; then echo xx is defined; fi
Graham
quelle
11
Willkommen bei StackOverflow. Während Ihre Antwort geschätzt wird, ist es am besten, mehr als nur Code zu geben. Könnten Sie Ihrer Antwort eine Begründung oder eine kleine Erklärung hinzufügen? Auf dieser Seite finden Sie weitere Ideen zur Erweiterung Ihrer Antwort.
Celeo
0

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
fr00tyl00p
quelle
1
Seit Bash 2.0+ ist eine indirekte Erweiterung verfügbar. Sie könnten die lange und komplexe (mit einer auch enthaltenen test -n "$(eval "echo "\${${1}+x}"")"[[ ${!1+x} ]]
0

Ich mag Hilfsfunktionen, um die groben Details von Bash zu verbergen. In diesem Fall wird dadurch noch mehr (versteckte) Grobheit hinzugefügt:

# The first ! negates the result (can't use -n to achieve this)
# the second ! expands the content of varname (can't do ${$varname})
function IsDeclared_Tricky
{
  local varname="$1"
  ! [ -z ${!varname+x} ]
}

Da ich zum ersten Mal Fehler in dieser Implementierung hatte (inspiriert von den Antworten von Jens und Lionel), habe ich eine andere Lösung gefunden:

# Ask for the properties of the variable - fails if not declared
function IsDeclared()
{
  declare -p $1 &>/dev/null
}

Ich finde es direkter, schüchterner und leichter zu verstehen / zu merken. Testfall zeigt, dass es äquivalent ist:

function main()
{
  declare -i xyz
  local foo
  local bar=
  local baz=''

  IsDeclared_Tricky xyz; echo "IsDeclared_Tricky xyz: $?"
  IsDeclared_Tricky foo; echo "IsDeclared_Tricky foo: $?"
  IsDeclared_Tricky bar; echo "IsDeclared_Tricky bar: $?"
  IsDeclared_Tricky baz; echo "IsDeclared_Tricky baz: $?"

  IsDeclared xyz; echo "IsDeclared xyz: $?"
  IsDeclared foo; echo "IsDeclared foo: $?"
  IsDeclared bar; echo "IsDeclared bar: $?"
  IsDeclared baz; echo "IsDeclared baz: $?"
}

main

Der Testfall auch zeigt , dass local varsich NICHT var erklären (es sei denn , durch ‚=‘ folgt). Seit einiger Zeit dachte ich, ich hätte Variablen auf diese Weise deklariert, nur um jetzt herauszufinden, dass ich nur meine Absicht ausgedrückt habe ... Es ist ein No-Op, denke ich.

IsDeclared_Tricky xyz: 1
IsDeclared_Tricky foo: 1
IsDeclared_Tricky-Balken: 0
IsDeclared_Tricky baz: 0
IsDeclared xyz: 1
IsDeclared foo: 1
IsDeclared-Balken: 0
IsDeclared baz: 0

BONUS: Anwendungsfall

Ich benutze diesen Test meistens, um Funktionen auf eine etwas "elegante" und sichere Weise (fast wie eine Schnittstelle ...) mit Parametern zu versehen (und zurückzugeben ):

#auxiliary functions
function die()
{
  echo "Error: $1"; exit 1
}

function assertVariableDeclared()
{
  IsDeclared "$1" || die "variable not declared: $1"
}

function expectVariables()
{
  while (( $# > 0 )); do
    assertVariableDeclared $1; shift
  done
}

# actual example
function exampleFunction()
{
  expectVariables inputStr outputStr
  outputStr="$inputStr world!"
}

function bonus()
{
  local inputStr='Hello'
  local outputStr= # remove this to trigger error
  exampleFunction
  echo $outputStr
}

bonus

Wenn mit all aufgerufen, müssen Variablen deklariert werden:

Hallo Welt!

sonst:

Fehler: Variable nicht deklariert: outputStr

Daniel S.
quelle
0

Nachdem Sie alle Antworten überflogen haben, funktioniert dies auch:

if [[ -z $SOME_VAR ]]; then read -p "Enter a value for SOME_VAR: " SOME_VAR; fi
echo "SOME_VAR=$SOME_VAR"

Wenn Sie nicht SOME_VARanstelle von dem setzen, was ich habe $SOME_VAR, wird es auf einen leeren Wert gesetzt. $ist notwendig, damit dies funktioniert.

Hatem Jaber
quelle
wird nicht funktionieren, wenn Sie set -uin der Tat haben, die den unboud variableFehler drucken wird
Michael Heuberger
0

Zusammenfassung

  • Verwenden Sie test -n "${var-}"diese Option , um zu überprüfen, ob die Variable nicht leer ist (und daher auch definiert / gesetzt werden muss).
  • Verwenden Sie test ! -z "${var+}"diese Option , um zu überprüfen, ob die Variable definiert / festgelegt ist (auch wenn sie leer ist).

Beachten Sie, dass der erste Anwendungsfall in Shell-Skripten viel häufiger vorkommt und dass Sie diesen normalerweise verwenden möchten.

Anmerkungen

  • Diese Lösung sollte in allen POSIX-Shells (sh, bash, zsh, ksh, dash) funktionieren.
  • Einige der anderen Antworten auf diese Frage sind korrekt, können jedoch für Personen, die noch keine Erfahrung mit Shell-Skripten haben, verwirrend sein. Daher wollte ich eine TLDR-Antwort bereitstellen, die für solche Personen am wenigsten verwirrend ist.

Erläuterung

Um zu verstehen, wie diese Lösung funktioniert, müssen Sie den POSIX- testBefehl und die Erweiterung der POSIX-Shell-Parameter ( Spezifikation ) verstehen. Lassen Sie uns also die absoluten Grundlagen behandeln, die zum Verständnis der Antwort erforderlich sind.

Der Testbefehl wertet einen Ausdruck aus und gibt true oder false zurück (über seinen Exit-Status). Der Operator -ngibt true zurück, wenn der Operand eine nicht leere Zeichenfolge ist. Gibt beispielsweise test -n "a"true zurück, während test -n ""false zurückgegeben wird. Um zu überprüfen, ob eine Variable nicht leer ist (was bedeutet, dass sie definiert werden muss), können Sie sie verwenden test -n "$var". Einige Shell-Skripte verfügen jedoch über eine Option set ( set -u), die bewirkt, dass Verweise auf undefinierte Variablen einen Fehler ausgeben. Wenn die Variable varnicht definiert ist, verursacht der Ausdruck $aeinen Fehler. Um diesen Fall korrekt zu behandeln, müssen Sie die Variablenerweiterung verwenden, die die Shell anweist, die Variable durch eine alternative Zeichenfolge zu ersetzen, wenn sie nicht definiert ist, um den oben genannten Fehler zu vermeiden.

Die Variablenerweiterung ${var-}bedeutet: Wenn die Variable varundefiniert ist (auch als "nicht gesetzt" bezeichnet), ersetzen Sie sie durch eine leere Zeichenfolge. Gibt also test -n "${var-}"true zurück, wenn $vares nicht leer ist. Dies ist fast immer das, was Sie in Shell-Skripten einchecken möchten. Die umgekehrte Prüfung, ob $varundefiniert oder nicht leer, wäre test -z "${var-}".

Nun zum zweiten Anwendungsfall: Überprüfen, ob die Variable vardefiniert ist, ob leer oder nicht. Dies ist ein weniger verbreiteter und etwas komplexer Anwendungsfall, und ich würde Ihnen raten, die großartige Antwort von Lionels zu lesen , um sie besser zu verstehen.

Infokiller
quelle
-1

Um zu überprüfen, ob eine Variable gesetzt ist oder nicht

var=""; [[ $var ]] && echo "set" || echo "not set"
Koola
quelle
3
Dies schlägt fehl, wenn $vardie leere Zeichenfolge festgelegt ist.
HelloGoodbye
-1

Wenn Sie testen möchten, ob eine Variable gebunden oder ungebunden ist, funktioniert dies auch dann, wenn Sie die Nomen-Set-Option aktiviert haben:

set -o noun set

if printenv variableName >/dev/null; then
    # variable is bound to a value
else
    # variable is unbound
fi
user1857592
quelle
Ich denke du meinst set -o nounsetnicht set -o noun set. Dies funktioniert nur für Variablen, die exportbearbeitet wurden. Außerdem werden Ihre Einstellungen so geändert, dass das Rückgängigmachen umständlich ist.
Keith Thompson