Umfasst dies, wenn eine Variable auf den Wert "" gesetzt ist?
Brent,
11
Ja, es werden ... "-z" Tests für eine Zeichenfolge mit der Länge Null durchgeführt.
David Z
91
if [ ! -z "$VAR" ];
Aaron Copley
263
das Gegenteil von -zist-nif [ -n "$VAR" ];
Felipe Alvarez
19
Die doppelten Anführungszeichen stellen sicher, dass die Variable nicht aufgeteilt wird. Ein einfaches $varElement in einer Befehlszeile wird durch sein Leerzeichen in eine Liste von Parametern aufgeteilt, wobei "$var"es sich immer nur um einen Parameter handelt. Das Zitieren von Variablen ist häufig eine gute Praxis und verhindert, dass Sie auf Dateinamen stoßen, die (unter anderem) Leerzeichen enthalten. Beispiel: a="x --help"Versuchen cat $aSie es anschließend mit der Hilfeseite für cat. Dann versuchen cat "$a"Sie es - es wird (normalerweise) sagen cat: x --help: No such file or directory. Kurz gesagt, zitiere früh und zitiere oft und du wirst es so gut wie nie bereuen.
Score_Under
247
Wenn Sie sich in Bash nicht mit der Portierbarkeit auf Shells befassen, die diese nicht unterstützen, sollten Sie immer die doppelte Klammer verwenden:
In Bash sind die Anführungszeichen in doppelten eckigen Klammern nicht erforderlich. Sie können den Test für eine Variable vereinfachen , die tut einen Wert enthalten:
if[[ $variable ]]
Diese Syntax ist mit ksh kompatibel (zumindest ksh93). Es funktioniert nicht in reinen POSIX- oder älteren Bourne-Shells wie sh oder dash.
Weitere Informationen zu den Unterschieden zwischen doppelten und einfachen eckigen Klammern finden Sie in meiner Antwort hier und in BashFAQ / 031 .
Sie können testen, ob eine Variable speziell nicht gesetzt ist (im Gegensatz zu einer leeren Zeichenfolge):
if[[-z ${variable+x}]]
wobei das "x" beliebig ist.
Wenn Sie wissen möchten, ob eine Variable null ist, aber nicht nicht gesetzt wurde:
Das if [[ $variable ]]hat für mich gut funktioniert und brauchte nicht einmal das set -u, was für eine der anderen vorgeschlagenen Lösungen erforderlich war.
Teemu Leisti
3
Ich denke, das ist besser als die akzeptierte Antwort.
qed
2
Warum empfehlen Sie eine nicht tragbare Funktion, wenn dies keinen Nutzen bringt?
Alastair Irvine
19
@AlastairIrvine: Ich erwähne die Portabilität im ersten Satz meiner Antwort, der Fragentitel und der Text enthalten das Wort "Bash" und die Frage ist mit bash markiert , und die doppelte Klammerstruktur bietet in vielerlei Hinsicht klare Vorteile . Und ich empfehle aus Gründen der Konsistenz und Wartbarkeit nicht, Bracket-Stile zu mischen. Wenn Sie maximale Portabilität mit dem niedrigsten gemeinsamen Nenner benötigen, verwenden Sie shanstelle von Bash. Wenn Sie die erweiterten Funktionen benötigen, verwenden Sie Bash und nutzen Sie es vollständig.
Dennis Williamson
2
@BrunoBronosky: Ich habe die Bearbeitung rückgängig gemacht. Es gibt keine Anforderung für ;am Ende. Die thenkann in der nächsten Zeile ohne Semikolon stehen.
Dennis Williamson
230
Eine Variable in bash (und jede POSIX-kompatible Shell) kann sich in einem von drei Zuständen befinden:
nicht gesetzt
auf die leere Zeichenkette setzen
Auf eine nicht leere Zeichenfolge setzen
Die meiste Zeit müssen Sie nur wissen, ob eine Variable auf eine nicht leere Zeichenfolge festgelegt ist, aber gelegentlich ist es wichtig, zwischen nicht festgelegt und auf die leere Zeichenfolge festgelegt zu unterscheiden.
Die folgenden Beispiele zeigen, wie Sie die verschiedenen Möglichkeiten testen können und ob dies in bash oder einer POSIX-kompatiblen Shell funktioniert:
if[-z "${VAR}"];then
echo "VAR is unset or set to the empty string"fiif[-z "${VAR+set}"];then
echo "VAR is unset"fiif[-z "${VAR-unset}"];then
echo "VAR is set to the empty string"fiif[-n "${VAR}"];then
echo "VAR is set to a non-empty string"fiif[-n "${VAR+set}"];then
echo "VAR is set, possibly to the empty string"fiif[-n "${VAR-unset}"];then
echo "VAR is either unset or set to a non-empty string"fi
Hier ist das Gleiche, aber in handlicher Tabellenform:
Das ${VAR+foo}Konstrukt wird zu der leeren Zeichenfolge erweitert, wenn VARes nicht festgelegt ist, oder zu, foowenn VARes auf etwas festgelegt ist (einschließlich der leeren Zeichenfolge).
Das ${VAR-foo}Konstrukt wird auf den Wert von VARif set (einschließlich set für die leere Zeichenfolge) und fooif unset erweitert. Dies ist nützlich, um vom Benutzer überschreibbare Standardeinstellungen bereitzustellen (z. B. ${COLOR-red}zu verwenden, es redsei denn, die Variable COLORwurde auf etwas festgelegt).
Der Grund, warum [ x"${VAR}" = x ]oft empfohlen wird, um zu testen, ob eine Variable entweder nicht gesetzt oder auf die leere Zeichenfolge gesetzt ist, liegt darin, dass einige Implementierungen des [Befehls (auch bekannt als test) fehlerhaft sind. Wenn VARauf so etwas wie gesetzt ist -n, werden einige Implementierungen bei der Angabe das Falsche tun, [ "${VAR}" = "" ]da das erste Argument zu [fälschlicherweise als -nOperator interpretiert wird , nicht als Zeichenfolge.
Das Testen für eine Variable, die auf die leere Zeichenfolge festgelegt ist, kann auch mit ausgeführt werden [ -z "${VAR-set}" ].
Nwellnhof
@nwellnhof: Danke! Ich habe meine Antwort aktualisiert, um die kürzere Syntax zu verwenden.
Richard Hansen
Was ist der Unterschied zwischen dem ersten und dem letzten Konstrukt? Beide entsprechen "VAR ist entweder nicht gesetzt oder auf eine nicht leere Zeichenfolge gesetzt".
Faheem Mitha
1
@FaheemMitha: Es ist nicht deine Schuld - meine Antwort war schwer zu lesen. Ich habe eine Tabelle hinzugefügt, um die Antwort hoffentlich klarer zu machen.
Richard Hansen
2
Die nicht gesetzten Prüfungen sind nicht zuverlässig. Wenn der Benutzer set -uoder set -o nounsetin bash anruft, führt der Test nur zum Fehler "bash: VAR: ungebundene Variable". Unter stackoverflow.com/a/13864829 finden Sie eine zuverlässigere Überprüfung auf nicht gesetzte Werte . Ich überprüfe, ob eine Variable null ist oder nicht [ -z "${VAR:-}" ]. Meine Prüfung, ob eine Variable nicht leer ist, ist [ "${VAR:-}" ].
Kevin Jin
38
-z ist der beste Weg.
Eine andere Option, die ich verwendet habe, ist das Setzen einer Variablen, die jedoch von einer anderen Variablen außer Kraft gesetzt werden kann, z
export PORT=${MY_PORT:-5432}
Wenn die $MY_PORTVariable leer ist, PORTwird sie auf 5432 gesetzt, andernfalls wird PORT auf den Wert von gesetzt MY_PORT. Beachten Sie, dass die Syntax den Doppelpunkt und den Bindestrich enthält.
Eine Alternative, die ich gesehen habe, [ -z "$foo" ]ist die folgende, aber ich bin nicht sicher, warum die Leute diese Methode anwenden, weiß jemand?
["x${foo}"="x"]
Wenn Sie nicht gesetzte Variablen (entweder von set -uoder set -o nounset) nicht zulassen, treten bei beiden Methoden Probleme auf. Hierfür gibt es eine einfache Lösung:
Es gibt einen Kommentar zur Alternative zu -zunter pubs.opengroup.org/onlinepubs/009695399/utilities/test.html . Grundsätzlich ist es keine Alternative zu -z. Vielmehr werden Fälle behandelt, in denen $fooeine Erweiterung auf einen Meta-Buchstaben möglich ist, der verwirrt ist [oder von testdiesem verwirrt wird. Wenn Sie am Anfang ein beliebiges Nicht-Metazeichen setzen, wird diese Möglichkeit ausgeschlossen.
James Sneeringer
6
Die Frage lautet , wie zu überprüfen ist, ob eine Variable eine leere Zeichenfolge ist, und die besten Antworten dafür sind bereits gegeben.
Aber ich bin hier gelandet, nachdem eine Zeit lang die Programmierung in PHP abgelaufen war, und was ich tatsächlich suchte, war eine Überprüfung wie die leere Funktion in PHP, die in einer Bash-Shell arbeitet.
Nachdem ich die Antworten gelesen hatte, stellte ich fest, dass ich in Bash nicht richtig dachte, aber in diesem Moment wäre eine Funktion wie leer in PHP in meinem Bash-Code soooo praktisch gewesen.
Wie ich glaube , dies anderen passieren kann, habe ich beschlossen , die PHP - leer - Funktion in bash zu konvertieren
Nach dem PHP - Handbuch : Eine Variable wird als leer betrachtet, wenn sie nicht existiert oder wenn ihr Wert einer der folgenden Werte ist:
"" (eine leere Zeichenfolge)
0 (0 als Ganzzahl)
0,0 (0 als Float)
"0" (0 als Zeichenfolge)
ein leeres Array
Eine deklarierte Variable, aber ohne Wert
Natürlich können die Groß- und Kleinschreibung nicht in Bash konvertiert werden, daher werden sie weggelassen.
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 passedif test -z "$var"then[[ $( echo "1")]]return# Return true if var is zero (0 as an integer or "0" as a string)elif["$var"==02>/dev/null ]then[[ $( echo "1")]]return# Return true if var is 0.0 (0 as a float)elif["$var"==0.02>/dev/null ]then[[ $( echo "1")]]returnfi[[ $( echo "")]]}
Anwendungsbeispiel:
if empty "${var}"then
echo "empty"else
echo "not empty"fi
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
In einer Bash-Logik können die Prüfungen auf Null in dieser Funktion imho Nebenprobleme verursachen. Jeder, der diese Funktion verwendet, sollte dieses Risiko bewerten und möglicherweise beschließen, diese Prüfungen abzuschneiden und nur die erste zu belassen.
Das wird scheitern, wenn foo nur Leerzeichen enthält
Brian
2
Scheitert auch in einigen Shells, wenn foo mit einem Bindestrich beginnt, da dies als Option interpretiert wird. ZB auf Solaris sind ksh , zsh und bash kein Problem, sh und / bin / test
schlagen
4
Dies gilt genau dann, wenn $ FOO gesetzt und leer ist:
Einige Shells akzeptieren kein doppeltes Gleichheitszeichen.
Dennis Williamson
1
Die Frage war über Bash. Ich benutze Bash. Funktioniert gut für mich. Über was genau sprichst du?
Fedir RYKHTIK
2
Wenn Sie Bash verwenden, sollten Sie doppelte eckige Klammern verwenden. Mein vorheriger Kommentar war eine einfache Feststellung für diejenigen, die möglicherweise Ihre Antwort lesen und eine andere Shell verwenden.
Dennis Williamson
einfache eckige Klammern sind in diesem Fall in Ordnung
Meine 5 Cent: Es gibt auch eine kürzere Syntax als if ...diese:
VALUE="${1?"Usage: $0 value"}"
Diese Zeile setzt VALUE, wenn ein Argument angegeben wurde, und gibt im Fehlerfall eine Fehlermeldung mit der Nummer der Skriptzeile aus (und beendet die Skriptausführung).
Ein weiteres Beispiel finden Sie im Abs -Guide (Suche nach «Beispiel 10-7»).
Keine exakte Antwort, aber auf diesen Trick gestoßen. Wenn die Zeichenfolge, nach der Sie suchen, von "einem Befehl" stammt, können Sie den Befehl tatsächlich in einer Umgebung speichern. Variable und führen Sie es dann jedes Mal für die if-Anweisung aus, dann sind keine Klammern erforderlich!
Zum Beispiel dieser Befehl, der bestimmt, ob Sie unter Debian sind:
Dies ist also wie eine indirekte Methode (es wird jedes Mal neu ausgeführt), um nach einer leeren Zeichenfolge zu suchen (es wird zufällig nach einer Fehlerantwort vom Befehl gesucht, es wird jedoch auch eine leere Zeichenfolge zurückgegeben).
Antworten:
Dies gibt true zurück, wenn eine Variable nicht gesetzt oder auf die leere Zeichenfolge ("") gesetzt ist.
quelle
if [ ! -z "$VAR" ];
-z
ist-n
if [ -n "$VAR" ];
$var
Element in einer Befehlszeile wird durch sein Leerzeichen in eine Liste von Parametern aufgeteilt, wobei"$var"
es sich immer nur um einen Parameter handelt. Das Zitieren von Variablen ist häufig eine gute Praxis und verhindert, dass Sie auf Dateinamen stoßen, die (unter anderem) Leerzeichen enthalten. Beispiel:a="x --help"
Versuchencat $a
Sie es anschließend mit der Hilfeseite fürcat
. Dann versuchencat "$a"
Sie es - es wird (normalerweise) sagencat: x --help: No such file or directory
. Kurz gesagt, zitiere früh und zitiere oft und du wirst es so gut wie nie bereuen.Wenn Sie sich in Bash nicht mit der Portierbarkeit auf Shells befassen, die diese nicht unterstützen, sollten Sie immer die doppelte Klammer verwenden:
Eines der folgenden:
In Bash sind die Anführungszeichen in doppelten eckigen Klammern nicht erforderlich. Sie können den Test für eine Variable vereinfachen , die tut einen Wert enthalten:
Diese Syntax ist mit ksh kompatibel (zumindest ksh93). Es funktioniert nicht in reinen POSIX- oder älteren Bourne-Shells wie sh oder dash.
Weitere Informationen zu den Unterschieden zwischen doppelten und einfachen eckigen Klammern finden Sie in meiner Antwort hier und in BashFAQ / 031 .
Sie können testen, ob eine Variable speziell nicht gesetzt ist (im Gegensatz zu einer leeren Zeichenfolge):
wobei das "x" beliebig ist.
Wenn Sie wissen möchten, ob eine Variable null ist, aber nicht nicht gesetzt wurde:
quelle
if [[ $variable ]]
hat für mich gut funktioniert und brauchte nicht einmal dasset -u
, was für eine der anderen vorgeschlagenen Lösungen erforderlich war.sh
anstelle von Bash. Wenn Sie die erweiterten Funktionen benötigen, verwenden Sie Bash und nutzen Sie es vollständig.;
am Ende. Diethen
kann in der nächsten Zeile ohne Semikolon stehen.Eine Variable in bash (und jede POSIX-kompatible Shell) kann sich in einem von drei Zuständen befinden:
Die meiste Zeit müssen Sie nur wissen, ob eine Variable auf eine nicht leere Zeichenfolge festgelegt ist, aber gelegentlich ist es wichtig, zwischen nicht festgelegt und auf die leere Zeichenfolge festgelegt zu unterscheiden.
Die folgenden Beispiele zeigen, wie Sie die verschiedenen Möglichkeiten testen können und ob dies in bash oder einer POSIX-kompatiblen Shell funktioniert:
Hier ist das Gleiche, aber in handlicher Tabellenform:
Das
${VAR+foo}
Konstrukt wird zu der leeren Zeichenfolge erweitert, wennVAR
es nicht festgelegt ist, oder zu,foo
wennVAR
es auf etwas festgelegt ist (einschließlich der leeren Zeichenfolge).Das
${VAR-foo}
Konstrukt wird auf den Wert vonVAR
if set (einschließlich set für die leere Zeichenfolge) undfoo
if unset erweitert. Dies ist nützlich, um vom Benutzer überschreibbare Standardeinstellungen bereitzustellen (z. B.${COLOR-red}
zu verwenden, esred
sei denn, die VariableCOLOR
wurde auf etwas festgelegt).Der Grund, warum
[ x"${VAR}" = x ]
oft empfohlen wird, um zu testen, ob eine Variable entweder nicht gesetzt oder auf die leere Zeichenfolge gesetzt ist, liegt darin, dass einige Implementierungen des[
Befehls (auch bekannt alstest
) fehlerhaft sind. WennVAR
auf so etwas wie gesetzt ist-n
, werden einige Implementierungen bei der Angabe das Falsche tun,[ "${VAR}" = "" ]
da das erste Argument zu[
fälschlicherweise als-n
Operator interpretiert wird , nicht als Zeichenfolge.quelle
[ -z "${VAR-set}" ]
.set -u
oderset -o nounset
in bash anruft, führt der Test nur zum Fehler "bash: VAR: ungebundene Variable". Unter stackoverflow.com/a/13864829 finden Sie eine zuverlässigere Überprüfung auf nicht gesetzte Werte . Ich überprüfe, ob eine Variable null ist oder nicht[ -z "${VAR:-}" ]
. Meine Prüfung, ob eine Variable nicht leer ist, ist[ "${VAR:-}" ]
.-z
ist der beste Weg.Eine andere Option, die ich verwendet habe, ist das Setzen einer Variablen, die jedoch von einer anderen Variablen außer Kraft gesetzt werden kann, z
Wenn die
$MY_PORT
Variable leer ist,PORT
wird sie auf 5432 gesetzt, andernfalls wird PORT auf den Wert von gesetztMY_PORT
. Beachten Sie, dass die Syntax den Doppelpunkt und den Bindestrich enthält.quelle
set -o nounset
in einigen Skripten tolerieren .Wenn Sie zwischen den Fällen "set-empty" und "unset" unterscheiden möchten, prüfen Sie die Option -u für bash:
quelle
Eine Alternative, die ich gesehen habe,
[ -z "$foo" ]
ist die folgende, aber ich bin nicht sicher, warum die Leute diese Methode anwenden, weiß jemand?Wenn Sie nicht gesetzte Variablen (entweder von
set -u
oderset -o nounset
) nicht zulassen, treten bei beiden Methoden Probleme auf. Hierfür gibt es eine einfache Lösung:Hinweis: Dadurch bleibt Ihre Variable undef.
quelle
-z
unter pubs.opengroup.org/onlinepubs/009695399/utilities/test.html . Grundsätzlich ist es keine Alternative zu-z
. Vielmehr werden Fälle behandelt, in denen$foo
eine Erweiterung auf einen Meta-Buchstaben möglich ist, der verwirrt ist[
oder vontest
diesem verwirrt wird. Wenn Sie am Anfang ein beliebiges Nicht-Metazeichen setzen, wird diese Möglichkeit ausgeschlossen.Die Frage lautet , wie zu überprüfen ist, ob eine Variable eine leere Zeichenfolge ist, und die besten Antworten dafür sind bereits gegeben.
Aber ich bin hier gelandet, nachdem eine Zeit lang die Programmierung in PHP abgelaufen war, und was ich tatsächlich suchte, war eine Überprüfung wie die leere Funktion in PHP, die in einer Bash-Shell arbeitet.
Nachdem ich die Antworten gelesen hatte, stellte ich fest, dass ich in Bash nicht richtig dachte, aber in diesem Moment wäre eine Funktion wie leer in PHP in meinem Bash-Code soooo praktisch gewesen.
Wie ich glaube , dies anderen passieren kann, habe ich beschlossen , die PHP - leer - Funktion in bash zu konvertieren
Nach dem PHP - Handbuch :
Eine Variable wird als leer betrachtet, wenn sie nicht existiert oder wenn ihr Wert einer der folgenden Werte ist:
Natürlich können die Groß- und Kleinschreibung nicht in Bash konvertiert werden, daher werden sie weggelassen.
Anwendungsbeispiel:
Demo:
das folgende Snippet:
Ausgänge:
In einer Bash-Logik können die Prüfungen auf Null in dieser Funktion imho Nebenprobleme verursachen. Jeder, der diese Funktion verwendet, sollte dieses Risiko bewerten und möglicherweise beschließen, diese Prüfungen abzuschneiden und nur die erste zu belassen.
quelle
empty
- warum hast du geschrieben[[ $( echo "1" ) ]] ; return
anstatt einfachreturn 1
?Das gesamte Wenn-Dann und -Z sind nicht erforderlich.
quelle
Dies gilt genau dann, wenn $ FOO gesetzt und leer ist:
quelle
Persönlich bevorzugen klarere Weise zu überprüfen:
quelle
Oneliner-Erweiterung der Lösung von duffbeer703 :
quelle
Meine 5 Cent: Es gibt auch eine kürzere Syntax als
if ...
diese:Diese Zeile setzt VALUE, wenn ein Argument angegeben wurde, und gibt im Fehlerfall eine Fehlermeldung mit der Nummer der Skriptzeile aus (und beendet die Skriptausführung).
Ein weiteres Beispiel finden Sie im Abs -Guide (Suche nach «Beispiel 10-7»).
quelle
Keine exakte Antwort, aber auf diesen Trick gestoßen. Wenn die Zeichenfolge, nach der Sie suchen, von "einem Befehl" stammt, können Sie den Befehl tatsächlich in einer Umgebung speichern. Variable und führen Sie es dann jedes Mal für die if-Anweisung aus, dann sind keine Klammern erforderlich!
Zum Beispiel dieser Befehl, der bestimmt, ob Sie unter Debian sind:
grep debian /proc/version
vollständiges Beispiel:
Dies ist also wie eine indirekte Methode (es wird jedes Mal neu ausgeführt), um nach einer leeren Zeichenfolge zu suchen (es wird zufällig nach einer Fehlerantwort vom Befehl gesucht, es wird jedoch auch eine leere Zeichenfolge zurückgegeben).
quelle