Frage Wie kann man feststellen, ob eine Bash-Variable leer ist?


Was ist der beste Weg festzustellen, ob eine Variable in bash leer ist ("")?

Ich habe gehört, dass es mir empfohlen wird if [ "x$variable" = "x" ]

Ist das das richtig Weg? (Es muss etwas einfacher sein)


719
2018-05-12 17:54


Ursprung




Antworten:


Dies wird true zurückgeben, wenn eine Variable nicht gesetzt oder auf die leere Zeichenfolge ("") gesetzt ist.

if [ -z "$VAR" ];

980
2018-05-12 18:06



Umfasst das, wenn eine Variable auf einen Wert von "" gesetzt ist? - Brent
Ja, das tut es ... "-z" testet auf eine Zeichenfolge mit der Länge Null. - David Z
if [ ! -z "$VAR" ]; - Aaron Copley
das Gegenteil von -z ist -n  if [ -n "$VAR" ]; - Felipe Alvarez
Die doppelten Anführungszeichen stellen sicher, dass die Variable nicht geteilt wird. Eine einfache $var auf einer Befehlszeile wird durch seine Whitespace in eine Liste von Parametern aufgeteilt, während "$var" wird immer nur ein Parameter sein. Das Zitieren von Variablen ist oft eine gute Übung und verhindert, dass Sie unter anderem über Dateinamen mit Whitespace stolpern. Beispiel: nach dem Tun a="x --help", Versuchen cat $a - es gibt Ihnen die Hilfeseite für cat. Dann versuche es cat "$a" - Es wird (normalerweise) sagen cat: x --help: No such file or directory. Kurz gesagt, zitieren Sie früh und zitieren Sie oft und Sie werden es fast nie bereuen. - Score_Under


Wenn Sie sich in Bash nicht mit der Übertragbarkeit auf Shells beschäftigen, die diese nicht unterstützen, sollten Sie immer die Double-Bracket-Syntax verwenden:

Eines der folgenden:

if [[ -z $variable ]]
if [[ -z "$variable" ]]
if [[ ! $variable ]]
if [[ ! "$variable" ]]

In Bash, mit doppelten eckigen Klammern, sind die Anführungszeichen nicht notwendig. Sie können den Test für eine Variable vereinfachen tut enthält einen Wert für:

if [[ $variable ]]

Diese Syntax ist kompatibel mit ksh (jedenfalls ksh93). Es funktioniert nicht in reinen POSIX- oder älteren Bourne-Shells wie sh oder dash.

Sehen meine Antwort hier und BashFAQ / 031 Weitere Informationen zu den Unterschieden zwischen doppelten und einzelnen eckigen Klammern.

Sie können testen, ob eine Variable speziell nicht gesetzt ist (im Gegensatz zu einer leeren Zeichenfolge):

if [[ -z ${variable+x} ]]

wo das "x" ist beliebig.

Wenn Sie wissen möchten, ob eine Variable null, aber nicht nicht gesetzt ist:

if [[ -z $variable && ${variable+x} ]]

227
2018-02-25 03:37



Das if [[ $variable ]] funktionierte gut für mich und brauchte nicht einmal die set -u das war von einer der anderen vorgeschlagenen Lösungen erforderlich. - Teemu Leisti
Ich denke, das ist besser als die angenommene Antwort. - qed
Warum empfehlen Sie eine nicht portable Funktion, wenn dies keinen Vorteil bringt? - Alastair Irvine
@AlastairIrvine: Ich erwähne Portabilität im ersten Satz meiner Antwort, die Frage Titel und Körper enthalten das Wort "Bash" und die Frage ist markiert bashund die doppelte Klammerstruktur bietet klare Vorteile auf viele Arten. Und ich rate aus Gründen der Konsistenz und Wartbarkeit nicht, Bracket Stile zu mischen. Wenn Sie die maximale Portabilität für den kleinsten gemeinsamen Nenner benötigen, verwenden Sie sh anstelle von Bash. Wenn Sie die erweiterten Funktionen benötigen, verwenden Sie Bash und verwenden Sie es vollständig. - Dennis Williamson
@BrunoBronosky: Ich habe die Bearbeitung rückgängig gemacht. Es gibt keine Voraussetzung für ; Am Ende. Das then kann in der nächsten Zeile ohne ein Semikolon sein. - Dennis Williamson


Eine Variable in bash (und jeder POSIX-kompatiblen Shell) kann sich in einem von drei Zuständen befinden:

  • nicht gesetzt
  • auf die leere Zeichenfolge festlegen
  • auf eine nicht leere Zeichenfolge festgelegt

Meistens müssen Sie nur wissen, ob eine Variable auf eine nicht leere Zeichenkette eingestellt ist, aber gelegentlich ist es wichtig, zwischen unset und der leeren Zeichenkette zu unterscheiden.

Im Folgenden finden Sie Beispiele, wie Sie die verschiedenen Möglichkeiten testen können, und es funktioniert in bash oder jeder POSIX-kompatiblen Shell:

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

Hier ist das Gleiche, aber in handlicher Tabellenform:

                        +-------+-------+-----------+
                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      |
+-----------------------+-------+-------+-----------+

Das ${VAR+foo} Konstrukt expandiert zu der leeren Zeichenfolge if VAR ist nicht festgelegt oder zu foo ob VAR ist auf alles eingestellt (einschließlich der leeren Zeichenfolge).

Das ${VAR-foo} Konstrukt expandiert auf den Wert von VAR wenn gesetzt (einschließlich auf den leeren String gesetzt) ​​und foo wenn nicht gesetzt. Dies ist nützlich, um vom Benutzer überschreibbare Standardwerte bereitzustellen (z. B. ${COLOR-red} sagt zu benutzen red außer die Variable COLOR wurde auf etwas eingestellt).

Der Grund warum [ x"${VAR}" = x ] wird oft empfohlen zu testen, ob eine Variable entweder nicht gesetzt ist oder auf die leere Zeichenkette gesetzt ist, weil einige Implementierungen der [ Befehl (auch bekannt als test) sind fehlerhaft. Ob VAR ist auf etwas wie eingestellt -n, dann werden einige Implementierungen das falsche tun, wenn sie gegeben werden [ "${VAR}" = "" ] weil das erste Argument zu [ wird irrtümlich als das interpretiert -n Operator, keine Zeichenfolge.


205
2018-04-24 20:39



Das Testen auf eine Variable, die auf die leere Zeichenfolge gesetzt ist, kann auch mit verwendet werden [ -z "${VAR-set}" ]. - nwellnhof
@nwellnhof: Danke! Ich habe meine Antwort aktualisiert, um die kürzere Syntax zu verwenden. - Richard Hansen
@FaheemMitha: Es ist nicht deine Schuld - meine Antwort war schwer zu lesen. Ich fügte eine Tabelle hinzu, um die Antwort hoffentlich klarer zu machen. - Richard Hansen
@RichardHansen: Danke, das ist eine sinnvolle Ergänzung. - Faheem Mitha
Die nicht gesetzten Überprüfungen sind nicht zuverlässig. Wenn der Benutzer anruft set -u oder set -o nounset in bash, dann wird der Test nur den Fehler "bash: VAR: nicht gebundene Variable" führen. Sehen stackoverflow.com/a/13864829 für eine zuverlässigere Schreckprüfung. Meine Suche nach, ob eine Variable null oder nicht gesetzt ist [ -z "${VAR:-}" ]. Meine Überprüfung ob eine Variable nicht leer ist ist [ "${VAR:-}" ]. - Kevin Jin


-z ist der beste Weg.

Eine andere Option, die ich verwendet habe, ist eine Variable zu setzen, aber sie kann auch durch eine andere Variable überschrieben werden

export PORT=${MY_PORT:-5432}

Wenn die $MY_PORT Variable ist dann leer PORT wird auf 5432 gesetzt, ansonsten wird PORT auf den Wert von gesetzt MY_PORT. Beachten Sie, dass die Syntax den Doppelpunkt und den Bindestrich enthält.


36
2018-06-11 13:19



Habe das heute zufällig gefunden, und es war genau das, was ich wollte. Vielen Dank! Ich muss es tolerieren set -o nounset in einigen Skripten. - opello


Wenn Sie daran interessiert sind, die Fälle von "Set-leer" gegenüber "Unset-Status" zu unterscheiden, sehen Sie sich die Option -u für bash an:

$ set -u
$ echo $BAR
bash: BAR: unbound variable
$ [ -z "$BAR" ] && echo true
bash: BAR: unbound variable
$ BAR=""
$ echo $BAR

$ [ -z "$BAR" ] && echo true
true

24
2018-05-12 18:21





Eine Alternative, die ich gesehen habe [ -z "$foo" ] ist das Folgende, aber ich bin mir nicht sicher, warum Menschen diese Methode verwenden, jemand weiß?

[ "x${foo}" = "x" ]

Jedenfalls, wenn Sie nicht gesetzte Variablen nicht zulassen (entweder durch set -u oder set -o nounset), dann werden Sie mit diesen beiden Methoden Probleme bekommen. Es gibt eine einfache Lösung dafür:

[ -z "${foo:-}" ]

Hinweis: Dadurch bleibt Ihre Variable undef.


8
2017-10-20 03:58



Es gibt einen Kommentar über die Alternative zu -z beim pubs.opengroup.org/onlinepubs/009695399/utilities/test.html. Grundsätzlich ist es keine Alternative zu -z. Vielmehr behandelt es Fälle, in denen $foo könnte sich zu etwas entwickeln, das mit einem Metazeichen beginnt, das [ oder test wäre verwirrt von. Durch das Einfügen eines beliebigen Nicht-Metazeichens am Anfang wird diese Möglichkeit eliminiert. - James Sneeringer


Das Frage fragt Wie überprüft man, ob eine Variable eine leere Zeichenfolge ist? und dafür sind die besten Antworten bereits gegeben.
Aber ich bin hier gelandet, nachdem eine Zeit lang die Programmierung in PHP abgelaufen war und was ich eigentlich suchte, war ein Scheck wie der leere Funktion in PHP Arbeiten in einer Bash Shell.
Nachdem ich die Antworten gelesen hatte, wurde mir klar, dass ich in der Bash nicht richtig dachte, aber irgendwie in diesem Moment eine Funktion wie leeren in php wäre soooo praktisch in meinem bash code gewesen.
Da ich denke, dass dies anderen passieren kann, habe ich beschlossen, die php empty Funktion in bash zu konvertieren

Laut 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 Gleitkommazahl)
  • "0" (0 als String)
  • ein leeres Array
  • eine Variable deklariert, aber ohne Wert

Natürlich Null und falsch cases können 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 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 "" ) ]]
}



Anwendungsbeispiel:

if empty "${var}"
    then
        echo "empty"
    else
        echo "not empty"
fi



Demo:
das folgende Snippet:

#!/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

Ausgänge:

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 zu Seitenproblemen führen, wer diese Funktion verwendet, sollte dieses Risiko auswerten und vielleicht entscheiden, diese Checks abzubrechen, so dass nur die erste übrig bleibt.


6
2017-08-31 20:11



Innerhalb der Funktion empty - warum hast du geschrieben [[ $( echo "1" ) ]] ; return statt einfach return 1 ? - Dor


das ganze Wenn-Dann und -z sind unnötig.

["$ foo"] && echo "foo ist nicht leer"
["$ foo"] || echo "foo ist in der Tat leer"

5
2018-01-26 14:02



Das wird fehlschlagen, wenn foo nur Leerzeichen enthält - Brian
Scheitert auch in einigen Shells wenn foo beginnt mit einem Bindestrich, da es als Option interpretiert wird. Z.B. auf Solaris ksh, zsh und bash sind kein Problem, Sch und / bin / test wird versagen - ktf


Dies gilt genau dann, wenn $ FOO gesetzt und leer ist:

[ "${FOO+x}" = x ] && [ -z "$FOO" ]

4
2018-05-20 20:52





Persönlich bevorzugen Sie einen klareren Weg zu überprüfen:

if [ "${VARIABLE}" == "" ]; then
  echo VARIABLE is empty
else
  echo VARIABLE is not empty
fi

4
2017-12-09 15:15



Einige Shells akzeptieren das doppelte Gleichheitszeichen nicht. - Dennis Williamson
Die Frage war Bash. Ich benutze Bash. Funktioniert gut für mich. Worüber genau sprichst du? - Fedir RYKHTIK
Wenn Sie Bash verwenden, sollten Sie doppelte eckige Klammern verwenden. Mein vorheriger Kommentar war eine einfache Tatsachenerklärung für diejenigen, die Ihre Antwort lesen und eine andere Shell verwenden könnten. - Dennis Williamson
einzelne eckige Klammern sind in diesem Fall ok, siehe bitte serverfault.com/questions/52034/... - Luca Borrione