Testen, ob eine Variable in einem Shell-Skript leer ist

27

Ich habe die folgende Technik gesehen, die oft bei vielen verschiedenen Shells angewendet wurde, um zu testen, ob eine Variable leer ist:

if [ "x$1" = "x" ]; then 
    # Variable is empty
fi

Gibt es irgendwelche Vorteile bei der Verwendung dieser Option gegenüber der kanonischeren if [ -z "$1" ]? Könnte es sich um ein Portabilitätsproblem handeln?

rahmu
quelle

Antworten:

17

Einige historische Shells implementierten einen sehr einfachen Parser, der verwirrt werden könnte, [ -n = "" ]wenn der erste Operand =wie ein Operator aussieht und dies als [ -n = ]Syntaxfehler interpretiert oder verursacht. In [ "x$1" = x"" ]stellt das xPräfix sicher, dass x"$1"es möglicherweise nicht wie ein Operator aussehen kann. Die Shell kann diesen Test also nur analysieren, indem sie ihn =als binären Operator behandelt.

Alle modernen Shells und sogar die meisten älteren Shells, die noch in Betrieb sind, folgen den POSIX-Regeln, die vorschreiben, dass alle Testausdrücke mit bis zu 4 Wörtern korrekt analysiert werden. Dies [ -z "$1" ]ist eine geeignete Methode zum Testen, ob $1leer ist , und [ "$x" = "$y" ]eine geeignete Methode zum Testen der Gleichheit zweier Variablen.

Sogar einige aktuelle Shells können mit längeren Ausdrücken verwechselt werden, und einige Ausdrücke sind tatsächlich mehrdeutig. Vermeiden Sie daher die Verwendung der Operatoren -aund -o, um längere boolesche Tests zu erstellen, und verwenden Sie stattdessen separate Aufrufe [der eigenen &&und ||booleschen Operatoren der Shell .

Gilles 'SO - hör auf böse zu sein'
quelle
3
Es sind nicht nur historische Muscheln. Einige ksh88-basierte shs auf einigen kommerziellen Unices haben immer noch das Problem. Einzelheiten finden Sie hier .
Stéphane Chazelas
Diese Aussage ist falsch: Dies [ -z "$1" ]ist eine geeignete Methode zum Testen, ob $1leer ist . sh -c '[ -z "$1" ]' ''; sh -c '[ -z "$1" ]'- beide geben 0 zurück, aber im zweiten Fall $1kann es nicht leer sein, da es nicht existiert.
mikeserv
3

Die obigen Tests verursachen auch einen Fehler, wenn Sie mit "set -u" oder "set -o nounset" ausführen.

Eine stabilere Möglichkeit, nach einer leeren Variablen zu suchen, ist die Verwendung der Parametererweiterung :

MYVAR = $ {MYVAR: - "Schlechter Wert"}

Diese Methode funktioniert für die traditionelle Bourne-Shell sowie für ksh und bash.

Scott Hoffman
quelle
2
Ich glaube, dies ist geschrieben als -> M = $ {M: - "Bad Value"}
Gyan
0
    function isBlank {
 valueNoSpaces=$(echo "$@" | tr -d ' ')

 if [  "$valueNoSpaces" == null ] || [ -z "$valueNoSpaces" ] 
 then
       echo true ;
 else
       echo ""  ;
 fi
}

#Test
if [ $(isBlank "      ") ] 
then
    echo "isBlank \"      \" : it's blank"
else
    echo " isBlank \"      \": it is not blank"
fi

if [ $(isBlank "abc") ] 

then
    echo "isBlank \"abc\" : it's blank"
else
    echo "isBlank \"abc\" :it is not blank"
fi

if [ $(isBlank null) ] 
then
      echo "isBlank null : it's blank"
else
    echo "isBlank null : it is not blank"
fi

if [ $(isBlank "") ] 
then
    echo "isBlank \"\" : it's blank"
else
    echo "isBlank \"\" : it is not blank"
fi

#Result
isBlank "      " : it's blank

isBlank "abc" :it is not blank

isBlank null : it's blank

isBlank "" : it's blank
Aslam Mohammed
quelle
3
Hallo! Ich bin mir nicht sicher , wie dies die Frage beantwortet, die fragt , warum die Verwendung im =Vergleich zu -zjetzt , wie.
Dhag