it-swarm-es.com

¿Cómo determinar si una variable 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 esa la forma correcta? (debe haber algo más sencillo)

784
Brent

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

if [ -z "$VAR" ];
1075
duffbeer703

En Bash, cuando no le preocupa la portabilidad a los shells que no lo admiten, siempre debe usar la sintaxis de doble paréntesis:

Cualquiera de los siguientes:

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

En Bash, usando corchetes dobles, las comillas no son necesarias. Puede simplificar la prueba para una variable que contiene un valor para:

if [[ $variable ]]

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

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

Puede probar para ver si una variable está específicamente desarmada (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á desarmada:

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

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

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

La mayoría de las veces solo necesita saber si una variable está establecida en una cadena no vacía, pero ocasionalmente es importante distinguir entre unset y set en la 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í está 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      |
+-----------------------+-------+-------+-----------+

La construcción ${VAR+foo} Se expande a la cadena vacía si VAR no está configurada o a foo si VAR está establecida en cualquier cosa (incluida la cadena vacía).

La construcción ${VAR-foo} Se expande al valor de VAR si se establece (incluido el conjunto en la cadena vacía) y foo si no se establece. 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 haya establecido 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 del 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 operador -n, no una cadena.

239
Richard Hansen

-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, luego PORT se establece en 5432; de lo contrario, PORT se establece en el valor de MY_PORT. Tenga en cuenta que la sintaxis incluye los dos puntos y el guión.

38
Rory

Si está interesado en distinguir los casos de estado set-empty versus unset, 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
MikeyB

Una alternativa que he visto para [ -z "$foo" ] es lo siguiente, sin embargo, no estoy seguro de por qué las personas usan este método, ¿alguien sabe?

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

De todos modos, si no permite 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á su variable undef.

8
errant.info

La pregunta pregunta cómo verificar si una variable es una cadena vacía y las mejores respuestas ya están dadas para eso.
Pero llegué aquí después de un período de programación en php y lo que realmente estaba buscando era un cheque como ¡función vacía en php trabajando en un bash Shell.
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ía en php hubiera sido muy útil en mi código de bash.
Como creo que esto puede pasarle a otros, decidí convertir la función vacía de php en bash

Según el 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 as an integer)
  • 0.0 (0 como flotante)
  • "0" (0 como una cadena)
  • una matriz vacía
  • una variable declarada, pero sin un valor

Por supuesto, los casos null y false 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:

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

Dicho esto, en una lógica bash, las comprobaciones de 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
Luca Borrione

Mis 5 centavos: también hay una sintaxis más corta que if ..., éste:

VALUE="${1?"Usage: $0 value"}"

Esta línea establecerá VALOR si se ha proporcionado un argumento e imprimirá un mensaje de error antepuesto con el número de línea del script en caso de error (y terminará la ejecución del script).

Otro ejemplo se puede encontrar en abs-guide (busque el "Ejemplo 10-7").

5
gluk47

todo el if-then y -z son innecesarios.

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

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

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

extensión oneliner de la solución de duffbeer7 :

#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter
4
andrej

Personalmente prefiero una forma más clara de verificar:

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

No es una respuesta exacta, pero me encontré con este truco. Si la cadena que busca proviene de "un comando", puede almacenar el comando en un entorno. variable y luego ejecutarlo cada vez para la instrucción if, ¡entonces no se requieren corchetes!

Por ejemplo, este comando, que determina si estás en Debian:

grep debian /proc/version

ejemplo completo:

IS_DEBIAN="grep -i debian /proc/version"

if $IS_DEBIAN; then
  echo 'yes debian'
else
  echo 'non debian'
fi

Entonces, esto es como una forma indirecta (volver a ejecutarlo cada vez) para verificar una cadena vacía (está comprobando la respuesta de error del comando, pero también está devolviendo una cadena vacía).

0
rogerdpack