¿Cuál es la mejor manera de determinar si una variable en bash está vacía ("")?
He escuchado que se recomienda que lo haga if [ "x$variable" = "x" ]
¿Es esa la forma correcta ? (debe haber algo más sencillo)
¿Cuál es la mejor manera de determinar si una variable en bash está vacía ("")?
He escuchado que se recomienda que lo haga if [ "x$variable" = "x" ]
¿Es esa la forma correcta ? (debe haber algo más sencillo)
Respuestas:
Esto devolverá verdadero si una variable se desarma o establece en la cadena vacía ("").
if [ -z "$VAR" ];
if [ ! -z "$VAR" ];
-z
es-n
if [ -n "$VAR" ];
$var
en una línea de comando se dividirá por su espacio en blanco en una lista de parámetros, mientras "$var"
que siempre será un solo parámetro. Citar variables a menudo es una buena práctica y le impide tropezar con nombres de archivos que contienen espacios en blanco (entre otras cosas). Ejemplo: después de hacerlo a="x --help"
, intente cat $a
, le dará la página de ayuda cat
. Luego intente cat "$a"
, lo dirá (generalmente) cat: x --help: No such file or directory
. En resumen, cite temprano y cite a menudo y casi nunca se arrepentirá.
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. Se puede simplificar la prueba para una variable que hace contener un valor de:
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.
Vea 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} ]]
if [[ $variable ]]
funcionó bien para mí y ni siquiera necesitaba lo set -u
que requería una de las otras soluciones propuestas.
sh
lugar de Bash. Si necesita las capacidades mejoradas que proporciona, use Bash y úselo completamente.
;
al final. El then
puede estar en la siguiente línea sin punto y coma.
Una variable en bash (y cualquier shell compatible con POSIX) puede estar en uno de tres estados:
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 ${VAR+foo}
construcción se expande a la cadena vacía si no VAR
está establecida o foo
si VAR
se establece en cualquier cosa (incluida la cadena vacía).
La ${VAR-foo}
construcción se expande al valor de VAR
if set (incluido el set a la cadena vacía) y foo
if unset. Esto es útil para proporcionar valores predeterminados reemplazables por el usuario (por ejemplo, ${COLOR-red}
dice usar a red
menos que la variable COLOR
se haya establecido en algo).
La razón por la [ x"${VAR}" = x ]
que 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
) tienen errores. Si VAR
se establece en algo así -n
, entonces algunas implementaciones harán lo incorrecto cuando se den [ "${VAR}" = "" ]
porque el primer argumento [
se interpreta erróneamente como el -n
operador, no como una cadena.
[ -z "${VAR-set}" ]
.
set -u
o set -o nounset
en bash, entonces la prueba solo dará como resultado el error "bash: VAR: variable independiente". Visite stackoverflow.com/a/13864829 para obtener una verificación sin configurar más confiable. Mi opción para verificar si una variable es nula o no está establecida [ -z "${VAR:-}" ]
. Mi verificación de si una variable no está vacía es [ "${VAR:-}" ]
.
-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 la $MY_PORT
variable está vacía, 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.
set -o nounset
en algunos guiones.
Si está interesado en distinguir los casos de estado de conjunto vacío frente a estado no establecido, 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
Una alternativa que he visto [ -z "$foo" ]
es la 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 establecidas (ya sea por set -u
o set -o nounset
), entonces tendrá problemas con ambos métodos. Hay una solución simple para esto:
[ -z "${foo:-}" ]
Nota: esto dejará su variable undef.
-z
en pubs.opengroup.org/onlinepubs/009695399/utilities/test.html . Básicamente, no está destinado a ser una alternativa a -z
. Más bien, se ocupa de los casos en que $foo
podría expandir a algo que comienza con un meta que [
o test
se confunde con. Poner un no metacarácter arbitrario al principio elimina esa posibilidad.
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 una verificación como la función vacía en php trabajando en un shell 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 hubiera sido muy útil en mi código bash.
Como creo que esto puede sucederle a otros, decidí convertir la función vacía de php en bash
De acuerdo con el manual de php :
una variable se considera vacía si no existe o si su valor es uno de los siguientes:
Por supuesto, los casos nulo y falso 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
Demostració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 en mi humilde opinión, cualquiera que use esta función debería evaluar este riesgo y tal vez decidir cortar esas comprobaciones dejando solo el primero.
empty
: ¿por qué escribiste en [[ $( echo "1" ) ]] ; return
lugar de simplemente return 1
?
todo el if-then y -z son innecesarios.
["$ foo"] && echo "foo no está vacío" ["$ foo"] || echo "foo está realmente vacío"
Esto es cierto exactamente cuando $ FOO está configurado y vacío:
[ "${FOO+x}" = x ] && [ -z "$FOO" ]
Personalmente prefiero una forma más clara de verificar:
if [ "${VARIABLE}" == "" ]; then
echo VARIABLE is empty
else
echo VARIABLE is not empty
fi
extensión oneliner de la solución de duffbeer703 :
#! /bin/bash
[ -z "$1" ] || some_command_that_needs_$1_parameter
Mis 5 centavos: también hay una sintaxis más corta que if ...
esta:
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).
Se puede encontrar otro ejemplo en la guía de abdominales (busque el «Ejemplo 10-7»).
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 necesitan 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).