Pregunta ¿Cómo determinar si una variable de bash está vacía?


¿Cuál es la mejor manera de determinar si una variable en bash está vacía ("")?

He oído que se recomienda que lo haga. if [ "x$variable" = "x" ]

Es que el correcto ¿camino? (Debe haber algo más sencillo)


719
2018-05-12 17:54


origen




Respuestas:


Esto devolverá verdadero si una variable no está establecida o se establece en la cadena vacía ("").

if [ -z "$VAR" ];

980
2018-05-12 18:06



¿Eso incluye si una variable se establece en un valor de ""? - Brent
Sí, lo hace ... "-z" prueba para una cadena de longitud cero. - David Z
if [ ! -z "$VAR" ]; - Aaron Copley
el inverso de -z es -n  if [ -n "$VAR" ]; - Felipe Alvarez
Las comillas dobles aseguran que la variable no se divida. Un simple $var en una línea de comando se dividirá por su espacio en blanco en una lista de parámetros, mientras que "$var" Siempre habrá un solo parámetro. Citar variables a menudo es una buena práctica y evita que se tropiece con nombres de archivos que contienen espacios en blanco (entre otras cosas). Ejemplo: después de hacer a="x --help", tratar cat $a - Te dará la página de ayuda para. cat. Entonces intenta cat "$a" - (usualmente) dirá cat: x --help: No such file or directory. En resumen, cita temprano y cita a menudo y casi nunca te arrepentirás. - Score_Under


En Bash, cuando no está preocupado por la portabilidad a shells que no lo admiten, siempre debe usar la sintaxis de doble corchete:

Cualquiera de los siguientes:

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

En Bash, utilizando corchetes dobles, las citas no son necesarias. Puede simplificar la prueba para una variable que hace contienen un valor para:

if [[ $variable ]]

Esta sintaxis es compatible con ksh (al menos ksh93, de todos modos). No funciona en POSIX puro o en versiones anteriores de Bourne, como sh o dash.

Ver mi respuesta aquí y BashFAQ / 031 Para más información sobre las diferencias entre corchetes dobles y simples.

Puede probar si una variable está específicamente no establecida (a diferencia de una cadena vacía):

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

donde la "x" es arbitraria.

Si desea saber si una variable es nula pero no está desactivada:

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

227
2018-02-25 03:37



Ese if [[ $variable ]] funcionó bien para mí, y ni siquiera necesitaba el set -u que fue requerido por una de las otras soluciones propuestas. - Teemu Leisti
Creo que esto es mejor que la respuesta aceptada. - qed
¿Por qué recomienda una función no portátil cuando hacerlo no ofrece ningún beneficio? - Alastair Irvine
@AlastairIrvine: menciono la portabilidad en la primera oración de mi respuesta, el título y el cuerpo de la pregunta contienen la palabra "Bash" y la pregunta está etiquetada golpetazo, y la estructura de doble soporte proporciona claras ventajas de muchas maneras. Y no recomiendo mezclar estilos de brackets por razones de consistencia y mantenimiento. Si necesita una portabilidad máxima, del denominador común más bajo, use sh en lugar de Bash. Si necesita las capacidades mejoradas que proporciona, use Bash y úselo completamente. - Dennis Williamson
@BrunoBronosky: revocé la edición. No hay ningún requisito para ; al final. los then puede estar en la siguiente línea sin un punto y coma en absoluto. - Dennis Williamson


Una variable en bash (y cualquier shell compatible con POSIX) puede estar en uno de tres estados:

  • desarmado
  • establecer en la cadena vacía
  • establecer en una cadena no vacía

La mayoría de las veces solo necesita saber si una variable está configurada en una cadena no vacía, pero en ocasiones es importante distinguir entre unset y una cadena vacía.

Los siguientes son ejemplos de cómo puede probar las diversas posibilidades, y funciona en bash o en cualquier shell compatible con POSIX:

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

Aquí es lo mismo pero en forma de tabla práctica:

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

los ${VAR+foo} la construcción se expande a la cadena vacía si VAR está sin configurar o para foo Si VAR se establece en nada (incluida la cadena vacía).

los ${VAR-foo} la construcción se expande al valor de VAR si está establecido (incluido el conjunto en la cadena vacía) y foo si no está configurado Esto es útil para proporcionar valores predeterminados reemplazables por el usuario (por ejemplo, ${COLOR-red} dice usar red a menos que la variable COLOR se ha fijado en algo).

La razón por la cual [ x"${VAR}" = x ] a menudo se recomienda para probar si una variable está desarmada o configurada en la cadena vacía es porque algunas implementaciones de [ comando (también conocido como test) son buggy. Si VAR se establece en algo como -n, entonces algunas implementaciones harán lo incorrecto cuando se den [ "${VAR}" = "" ] porque el primer argumento para [ Se interpreta erróneamente como el -n operador, no una cadena.


205
2018-04-24 20:39



La prueba de un conjunto de variables a la cadena vacía también se puede hacer usando [ -z "${VAR-set}" ]. - nwellnhof
@nwellnhof: ¡Gracias! Actualicé mi respuesta para usar la sintaxis más breve. - Richard Hansen
@FaheemMitha: No es tu culpa, mi respuesta fue difícil de leer. Agregué una tabla para hacer más clara la respuesta. - Richard Hansen
@RichardHansen: Gracias, es una adición útil. - Faheem Mitha
Los cheques sin establecer no son confiables. Si el usuario llama set -u o set -o nounset en bash, la prueba solo generará el error "bash: VAR: variable no vinculada". Ver stackoverflow.com/a/13864829 Para un chequeo más confiable sin establecer. Mi consulta para comprobar si una variable es nula o no está configurada [ -z "${VAR:-}" ]. Mi comprobación de si una variable no está vacía es [ "${VAR:-}" ]. - Kevin Jin


-z Es la mejor manera.

Otra opción que he usado es establecer una variable, pero puede ser anulada por otra variable, por ejemplo,

export PORT=${MY_PORT:-5432}

Si el $MY_PORT la variable está vacía, entonces PORT se establece en 5432, de lo contrario, PORT se establece en el valor de MY_PORT. Note que la sintaxis incluye los dos puntos y el guión.


36
2018-06-11 13:19



Accidentalmente encontré esto hoy, y era exactamente lo que quería. ¡Gracias! Tengo que tolerar set -o nounset en algunos guiones. - opello


Si está interesado en distinguir los casos de estado de conjunto vacío frente a desarmado, mire la opción -u para bash:

$ 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





Un suplente que he visto [ -z "$foo" ] es lo siguiente, sin embargo, no estoy seguro de por qué la gente usa este método, ¿alguien lo sabe?

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

De todos modos, si no está permitiendo las variables no definidas (ya sea por set -u o set -o nounset), entonces tendrás problemas con ambos métodos. Hay una solución simple para esto:

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

Nota: esto dejará tu variable undef.


8
2017-10-20 03:58



Hay un comentario sobre la alternativa a -z a pubs.opengroup.org/onlinepubs/009695399/utilities/test.html. Básicamente, no pretende ser una alternativa a -z. Más bien, maneja casos donde $foo podría expandirse a algo que comienza con un metacarácter que [ o test Sería confundido por. Poner un no-metacarácter arbitrario al principio elimina esa posibilidad. - James Sneeringer


los pregunta pregunta cómo comprobar si una variable es una cadena vacía y las mejores respuestas ya están dadas para eso.
Pero aterricé aquí después de un período de programación en PHP y lo que realmente estaba buscando era un cheque como el función vacía en php trabajando en una concha de bash.
Después de leer las respuestas, me di cuenta de que no estaba pensando correctamente en bash, pero de todos modos en ese momento una función como vacío en PHP habría sido tan útil en mi código de bash.
Como creo que esto puede suceder a otros, decidí convertir la función php vacía en bash

De acuerdo con la manual de php:
una variable se considera vacía si no existe o si su valor es uno de los siguientes:

  • "" (una cadena vacía)
  • 0 (0 como un entero)
  • 0.0 (0 como flotador)
  • "0" (0 como una cadena)
  • una matriz vacía
  • Una variable declarada, pero sin valor.

Por supuesto el nulo y falso los casos no se pueden convertir en bash, por lo que se omiten.

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 "" ) ]]
}



Ejemplo de uso:

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



Manifestación:
el siguiente fragmento de código:

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

salidas:

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

Habiendo dicho que en una lógica de bash, las comprobaciones en cero en esta función pueden causar problemas secundarios. Cualquiera que use esta función debería evaluar este riesgo y tal vez decidir cortar esas comprobaciones dejando solo la primera.


6
2017-08-31 20:11



Dentro de la funcion empty - por qué escribiste [[ $( echo "1" ) ]] ; return en lugar de simplemente return 1 ? - Dor


todo el if-then y -z son innecesarios.

["$ foo"] && echo "foo no está vacío"
["$ foo"] || echo "foo está realmente vacío"

5
2018-01-26 14:02



Eso fallará si foo contiene solo espacios - Brian
También fallará en algunas conchas si foo comienza con un guión ya que se interpreta como una opción. P.ej. en solaris ksh, zsh y golpetazo no hay problema sh y / bin / test fallará - ktf


Esto es cierto exactamente cuando $ FOO está configurado y vacío:

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

4
2018-05-20 20:52