Prueba si una variable está vacía en un script de shell

27

He visto la siguiente técnica utilizada muchas veces en muchos shells diferentes, para probar si una variable está vacía:

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

¿Hay alguna ventaja en usar esto sobre los más canónicos if [ -z "$1" ]? ¿Podría ser un problema de portabilidad?

rahmu
fuente

Respuestas:

17

Algunos shells históricos implementaron un analizador muy simple que podría confundirse con cosas como [ -n = "" ]donde el primer operando se =parece a un operador, y analizaría esto [ -n = ]o causaría un error de sintaxis. En [ "x$1" = x"" ], el xprefijo garantiza que x"$1"no pueda parecer un operador, por lo que la única forma en que el shell puede analizar esta prueba es tratando =como un operador binario.

Todos los shells modernos, e incluso los más antiguos aún en funcionamiento, siguen las reglas POSIX que exigen que todas las expresiones de prueba de hasta 4 palabras se analicen correctamente. Entonces, [ -z "$1" ]es una forma adecuada de probar si $1está vacía , y [ "$x" = "$y" ]es una forma adecuada de probar la igualdad de dos variables.

Incluso algunos shells actuales pueden confundirse con expresiones más largas, y algunas expresiones son realmente ambiguas, por lo tanto, evite usar los operadores -ay -opara construir pruebas booleanas más largas y, en su lugar, use llamadas separadas [y los operadores propios &&y ||booleanos del shell .

Gilles 'SO- deja de ser malvado'
fuente
3
No se trata solo de conchas históricas . Algunos ksh88 basados shen algunos Unices comerciales todavía tienen el problema. Ver aquí para más detalles.
Stéphane Chazelas
Esta declaración es incorrecta: [ -z "$1" ]es una forma adecuada de probar si $1está vacía . sh -c '[ -z "$1" ]' ''; sh -c '[ -z "$1" ]'- ambos devuelven 0, pero en el segundo caso $1no puede estar vacío porque no existe.
mikeserv
3

Las pruebas anteriores también causarán un error si ejecuta con "set -u" o "set -o nounset"

Una forma más estable de verificar una variable vacía sería usar la expansión de parámetros :

MYVAR = $ {MYVAR: - "Valor incorrecto"}

Este método funciona para el shell bourne tradicional, así como para ksh y bash.

Scott Hoffman
fuente
2
Creo que esto se escribe como -> 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
fuente
3
¡Hola! No estoy seguro de cómo esto responde a la pregunta, que pregunta por qué usar =versus -z, ahora cómo.
dhag