¿Cómo comprobar si una variable está establecida en Bash?
¿Cómo sé si una variable está establecida en Bash?
Por ejemplo, ¿cómo puedo comprobar si el usuario dio el primer parámetro a una función?
function a {
# if $1 is set ?
}
30 answers
(Generalmente) De la manera correcta
if [ -z ${var+x} ]; then echo "var is unset"; else echo "var is set to '$var'"; fi
Donde ${var+x}
es una expansión de parámetro que se evalúa como nada si var
no está configurado, y sustituye la cadena x
de lo contrario.
Comillas Digresión
Las comillas se pueden omitir (por lo que podemos decir ${var+x}
en lugar de "${var+x}"
) porque esta sintaxis y uso garantiza que esto solo se expandirá a algo que no requiere comillas (ya que se expande a x
(que no contiene saltos de palabra por lo que no necesita comillas), o nada (que resulta en [ -z ]
, que convenientemente evalúa al mismo valor (verdadero) que [ -z "" ]
también)).
Sin embargo, mientras que las citas se pueden omitir con seguridad, y no era inmediatamente obvio para todos (ni siquiera era aparente para el primer autor de esta explicación de citas que también es un codificador de Bash importante), a veces sería mejor escribir la solución con comillas como [ -z "${var+x}" ]
, con el costo muy pequeño posible de una penalización de velocidad O(1). El primer autor también agregó esto como un comentario junto al código que usa esta solución dando la URL a esta respuesta, que ahora también incluye la explicación de por qué las comillas se pueden omitir de forma segura.
(A menudo) El camino equivocado
if [ -z "$var" ]; then echo "var is blank"; else echo "var is set to '$var'"; fi
Esto a menudo es incorrecto porque no distingue entre una variable que no está establecida y una variable que está establecida en la cadena vacía. Es decir, si var=''
, entonces la solución anterior generará "var está en blanco".
La distinción entre unset y " set to the empty string " es esencial en situaciones en las que el usuario tiene que especificar una extensión, o una lista adicional de propiedades, y que no especificarlas por defecto es un valor no vacío, mientras que especificar la cadena vacía debería hacer que el script use una extensión vacía o una lista de propiedades adicionales.
Sin embargo, la distinción puede no ser esencial en todos los escenarios. En esos casos [ -z "$var" ]
estará bien.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-15 18:39:20
Para verificar la variable de cadena no nula/no nula, es decir, si se establece, use
if [ -n "$1" ]
Es lo contrario de -z
. Me encuentro usando -n
más que -z
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-13 15:42:36
He aquí cómo probar si un parámetro está sin establecer , o vacío ("nulo") o establecido con un valor :
+--------------------+----------------------+-----------------+-----------------+
| | parameter | parameter | parameter |
| | Set and Not Null | Set But Null | Unset |
+--------------------+----------------------+-----------------+-----------------+
| ${parameter:-word} | substitute parameter | substitute word | substitute word |
| ${parameter-word} | substitute parameter | substitute null | substitute word |
| ${parameter:=word} | substitute parameter | assign word | assign word |
| ${parameter=word} | substitute parameter | substitute null | assign word |
| ${parameter:?word} | substitute parameter | error, exit | error, exit |
| ${parameter?word} | substitute parameter | substitute null | error, exit |
| ${parameter:+word} | substitute word | substitute null | substitute null |
| ${parameter+word} | substitute word | substitute word | substitute null |
+--------------------+----------------------+-----------------+-----------------+
Fuente: POSIX: Expansión de parámetros :
En todos los casos que se muestran con "sustituir", la expresión se sustituye por el valor que se muestra. En todos los casos mostrados con "assign", al parámetro se le asigna ese valor, que también reemplaza la expresión.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-11 17:19:35
Hay muchas maneras de hacer esto con la siguiente siendo una de ellas:
if [ -z "$1" ]
Esto tiene éxito si $1 es null o unset
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-07 22:55:45
Mientras que la mayoría de las técnicas indicadas aquí son correctas, bash 4.2 soporta una prueba real para la presencia de una variable ( man bash), en lugar de probar el valor de la variable.
[[ -v foo ]]; echo $?
# 1
foo=bar
[[ -v foo ]]; echo $?
# 0
foo=""
[[ -v foo ]]; echo $?
# 0
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-11 19:46:43
Para ver si una variable no está vacía, utilizo
if [[ $var ]]; then ... # `$var' expands to a nonempty string
Las pruebas opuestas si una variable está desajustada o vacía:
if [[ ! $var ]]; then ... # `$var' expands to the empty string (set or not)
Para ver si se establece una variable (vacía o no vacía), utilizo
if [[ ${var+x} ]]; then ... # `var' exists (empty or nonempty)
if [[ ${1+x} ]]; then ... # Parameter 1 exists (empty or nonempty)
Las pruebas opuestas si una variable no está establecida:
if [[ ! ${var+x} ]]; then ... # `var' is not set at all
if [[ ! ${1+x} ]]; then ... # We were called with no arguments
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-08 08:32:46
Siempre encuentro la tabla POSIX en la otra respuesta lento para grok, así que aquí está mi opinión sobre ella:
+----------------------+------------+-----------------------+-----------------------+
| if VARIABLE is: | set | empty | unset |
+----------------------+------------+-----------------------+-----------------------+
- | ${VARIABLE-default} | $VARIABLE | "" | "default" |
= | ${VARIABLE=default} | $VARIABLE | "" | $(VARIABLE="default") |
? | ${VARIABLE?default} | $VARIABLE | "" | exit 127 |
+ | ${VARIABLE+default} | "default" | "default" | "" |
+----------------------+------------+-----------------------+-----------------------+
:- | ${VARIABLE:-default} | $VARIABLE | "default" | "default" |
:= | ${VARIABLE:=default} | $VARIABLE | $(VARIABLE="default") | $(VARIABLE="default") |
:? | ${VARIABLE:?default} | $VARIABLE | exit 127 | exit 127 |
:+ | ${VARIABLE:+default} | "default" | "" | "" |
+----------------------+------------+-----------------------+-----------------------+
Tenga en cuenta que cada grupo (con y sin dos puntos anteriores) tiene los mismos casos establecidosy no establecidos, por lo que lo único que difiere es cómo se manejan los casos vacíos.
Con los dos puntos anteriores, los vacíos y desajustados casos son idénticos, por lo que usaría esos siempre que sea posible (es decir, use :=
, no solo =
, porque el caso vacío es inconsistente).
De la rúbrica:
-
set significa
VARIABLE
no está vacío (VARIABLE="something"
) -
empty significa {[3] } es empty / null (
VARIABLE=""
) -
unset significa
VARIABLE
no existe (unset VARIABLE
)
Valores:
-
$VARIABLE
significa que el resultado es el valor original de la variable. -
"default"
significa que el resultado fue la cadena de reemplazo proporcionada. -
""
significa el resultado es null (una cadena vacía). -
exit 127
significa que el script deja de ejecutarse con el código de salida 127. -
$(VARIABLE="default")
significa que el resultado es el valor original de la variable y la cadena de reemplazo proporcionada se asigna a la variable para uso futuro.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-24 16:48:20
En una versión moderna de Bash (4.2 o posterior, creo; no lo sé con seguridad), probaría esto:
if [ ! -v SOMEVARIABLE ] #note the lack of a $ sigil
then
echo "Variable is unset"
elif [ -z "$SOMEVARIABLE" ]
then
echo "Variable is set to an empty string"
else
echo "Variable is set to some string"
fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-10 16:02:25
if [ "$1" != "" ]; then
echo \$1 is set
else
echo \$1 is not set
fi
Aunque para los argumentos normalmente es mejor probar $#, que es el número de argumentos, en mi opinión.
if [ $# -gt 0 ]; then
echo \$1 is set
else
echo \$1 is not set
fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-30 16:43:46
Lea la sección "Expansión de parámetros" de la página de manual de bash
. La expansión de parámetros no proporciona una prueba general para una variable que se está estableciendo, pero hay varias cosas que puede hacer a un parámetro si no está establecido.
Por ejemplo:
function a {
first_arg=${1-foo}
# rest of the function
}
Establecerá first_arg
igual a $1
si se asigna, de lo contrario utiliza el valor "foo". Si a
absolutamente debe tomar un solo parámetro, y no existe un buen valor predeterminado, puede salir con un mensaje de error cuando no hay parámetro dado:
function a {
: ${1?a must take a single argument}
# rest of the function
}
(Tenga en cuenta el uso de :
como un comando null, que solo expande los valores de sus argumentos. No queremos hacer nada con $1
en este ejemplo, solo salir si no está configurado)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-31 22:05:06
Desea salir si no está configurado
Esto funcionó para mí. Quería que mi script saliera con un mensaje de error si no se había establecido un parámetro.
#!/usr/bin/env bash
set -o errexit
# Get the value and empty validation check all in one
VER="${1:?You must pass a version of the format 0.0.0 as the only argument}"
Esto regresa con un error cuando se ejecuta
peek@peek:~$ ./setver.sh
./setver.sh: line 13: 1: You must pass a version of the format 0.0.0 as the only argument
Solo marque, sin salida: Vacío y sin configurar no son VÁLIDOS
Pruebe esta opción si solo desea comprobar si el valor set=VALID o unset/empty=INVALID.
TSET="good val"
TEMPTY=""
unset TUNSET
if [ "${TSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID
if [ "${TUNSET:-}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID
O, Incluso, pruebas cortas; -)
[ "${TSET:-}" ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY:-}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET:-}" ] && echo "VALID" || echo "INVALID"
Solo marque, sin salida-Solo vacío no es VÁLIDO
Y esto es la respuesta a la pregunta. Use esto si solo desea comprobar si el valor set/empty=VALID o unset=INVALID.
NOTA, el "1" en "..-1}" es insignificante, puede ser cualquier cosa (como x)
TSET="good val"
TEMPTY=""
unset TUNSET
if [ "${TSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TEMPTY+1}" ]; then echo "VALID"; else echo "INVALID";fi
# VALID
if [ "${TUNSET+1}" ]; then echo "VALID"; else echo "INVALID";fi
# INVALID
Pruebas cortas
[ "${TSET+1}" ] && echo "VALID" || echo "INVALID"
[ "${TEMPTY+1}" ] && echo "VALID" || echo "INVALID"
[ "${TUNSET+1}" ] && echo "VALID" || echo "INVALID"
Dedico esta respuesta a @mklement0 (comentarios) quien me desafió a responder la pregunta con precisión.
Referencia http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-16 04:46:12
Para comprobar si una variable está configurada con un valor no vacío, utilice [ -n "$x" ]
, como ya han indicado otros.
La mayoría de las veces, es una buena idea tratar una variable que tiene un valor vacío de la misma manera que una variable que no está establecida. Pero puedes distinguir los dos si necesitas: [ -n "${x+set}" ]
("${x+set}"
se expande a set
si x
está establecido y a la cadena vacía si x
no está establecido).
Para comprobar si se ha pasado un parámetro, pruebe $#
, que es el número de parámetros pasados a la función (o al script, cuando no está en una función) (ver La respuesta de Pablo).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:53
En bash puedes usar -v
dentro del [[ ]]
incorporado:
#! /bin/bash -u
if [[ ! -v SOMEVAR ]]; then
SOMEVAR='hello'
fi
echo $SOMEVAR
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-28 21:13:34
Para aquellos que buscan comprobar si no está configurado o está vacío cuando está en un script con set -u
:
if [ -z "${var-}" ]; then
echo "Must provide var environment variable. Exiting...."
exit 1
fi
Regular [ -z "$var" ]
verificación fallará con var; unbound variable
si set -u
pero [ -z "${var-}" ]
expande a cadena vacía si var
no está definida, sin fallar.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-16 11:26:13
Puedes hacer:
function a {
if [ ! -z "$1" ]; then
echo '$1 is set'
fi
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-31 07:23:26
Las respuestas anteriores no funcionan cuando la opción Bash set -u
está habilitada. Además, no son dinámicos, por ejemplo, ¿cómo probar es variable con el nombre "dummy" se define? Prueba esto:
is_var_defined()
{
if [ $# -ne 1 ]
then
echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
exit 1
fi
# Tricky. Since Bash option 'set -u' may be enabled, we cannot directly test if a variable
# is defined with this construct: [ ! -z "$var" ]. Instead, we must use default value
# substitution with this construct: [ ! -z "${var:-}" ]. Normally, a default value follows the
# operator ':-', but here we leave it blank for empty (null) string. Finally, we need to
# substitute the text from $1 as 'var'. This is not allowed directly in Bash with this
# construct: [ ! -z "${$1:-}" ]. We need to use indirection with eval operator.
# Example: $1="var"
# Expansion for eval operator: "[ ! -z \${$1:-} ]" -> "[ ! -z \${var:-} ]"
# Code execute: [ ! -z ${var:-} ]
eval "[ ! -z \${$1:-} ]"
return $? # Pedantic.
}
Relacionado: En Bash, ¿cómo pruebo si una variable está definida en modo" - u "
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:27
Usar [[ -z "$var" ]]
es la forma más fácil de saber si una variable se estableció o no, pero esa opción -z
no distingue entre una variable sin establecer y una variable establecida en una cadena vacía:
$ set=''
$ [[ -z "$set" ]] && echo "Set" || echo "Unset"
Unset
$ [[ -z "$unset" ]] && echo "Set" || echo "Unset"
Unset
Lo mejor es comprobarlo según el tipo de variable: variable env, parámetro o variable regular.
Para una variable env:
[[ $(env | grep "varname=" | wc -l) -eq 1 ]] && echo "Set" || echo "Unset"
Para un parámetro (por ejemplo, para comprobar la existencia de parámetro $5
):
[[ $# -ge 5 ]] && echo "Set" || echo "Unset"
Para una variable regular (usando un auxiliar función, para hacerlo de una manera elegante):
function declare_var {
declare -p "$1" &> /dev/null
return $?
}
declare_var "var_name" && echo "Set" || echo "Unset"
Notas:
$#
: dice que el número de parámetros posicionales.declare -p
: le da la definición de la variable pasada como parámetro. Si existe, devuelve 0, si no, devuelve 1 e imprime un mensaje de error.$?
: le da el código de estado del último comando ejecutado.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-10 08:10:51
En un shell puedes usar el operador -z
que es True si la longitud de la cadena es cero.
Una simple línea para establecer por defecto MY_VAR
si no está establecido, de lo contrario opcionalmente puede mostrar el mensaje:
[[ -z "$MY_VAR" ]] && MY_VAR="default"
[[ -z "$MY_VAR" ]] && MY_VAR="default" || echo "Variable already set."
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-10 16:04:12
Mi camino preferido es este:
$var=10
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$unset var
$if ! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set
Así que básicamente, si una variable se establece, se convierte en "una negación del resultado false
" (lo que será true
= "se establece").
Y, si no está configurado, se convertirá en "una negación del resultado true
" (ya que el resultado vacío se evalúa como true
) (por lo que terminará como false
= "NO establecido").
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-10 16:05:00
if [[ ${1:+isset} ]]
then echo "It was set and not null." >&2
else echo "It was not set or it was null." >&2
fi
if [[ ${1+isset} ]]
then echo "It was set but might be null." >&2
else echo "It was was not set." >&2
fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-30 05:22:39
He encontrado un código (mucho) mejor para hacer esto si quieres comprobar algo en $@
.
if [[ $1 = "" ]] then echo '$1 is blank' else echo '$1 is filled up' fi
¿Por qué todo esto? Todo en $@
existe en Bash, pero por defecto está en blanco, así que test -z
y test -n
no podrían ayudarte.
Actualizar: También puede contar el número de caracteres en un parámetro.
if [ ${#1} = 0 ] then echo '$1 is blank' else echo '$1 is filled up' fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-27 16:30:37
[[ $foo ]]
O
(( ${#foo} ))
O
let ${#foo}
O
declare -p foo
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-11 05:43:17
if [[ ${!xx[@]} ]] ; then echo xx is defined; fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-12 18:43:56
Siempre uso este, basado en el hecho de que parece fácil de ser entendido por cualquiera que vea el código por primera vez:
if [ "$variable" = "" ]
then
echo "Variable X is empty"
fi
Y, si quiere comprobar si no está vacío;
if [ ! "$variable" = "" ]
then
echo "Variable X is not empty"
fi
Eso es todo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-10 16:03:35
Esto es lo que uso todos los días:
#
# Check if a variable is set
# param1 name of the variable
#
function is_set()
{
[[ -n "${1}" ]] && test -n "$(eval "echo "\${${1}+x}"")"
}
Esto funciona bien bajo Linux y Solaris hasta bash 3.0.
bash-3.00$ myvar="TEST"
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ mavar=""
bash-3.00$ is_set myvar ; echo $?
0
bash-3.00$ unset myvar
bash-3.00$ is_set myvar ; echo $?
1
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-10 16:06:00
Si var
puede ser una matriz, entonces [ -z "${var+x}" ]
la sustitución de parámetros es incorrecta. Para estar realmente seguro en Bash necesita usar sintaxis de matriz como [ "${#var[@]}" = 0 ]
, como se muestra a continuación.
is-var-set () {
results="\${var+x}=${var+x}\t\${#var[@]}=${#var[@]}"
if [ -z "${var+x}" ] && [ "${#var[@]}" = 0 ]; then
echo -e "$1: var's unset.\t$results"
elif [ -n "${var+x}" ] && [ "${#var[@]}" != 0 ]; then
echo -e "$1: var is set. \t$results"
else
echo -e "$1: Is var set? \t$results"
fi
unset var # so we don't have to do it everywhere else
}
En casi todos los casos, están de acuerdo. La única situación que he encontrado donde el método array es más preciso es cuando la variable es un array no vacío con position 0
unset (por ejemplo, en tests 7
y A
más abajo). Este desacuerdo viene de $var
siendo la abreviatura de ${var[0]}
, por lo que [ -z "${var+x}" ]
no está comprobando la todo el arsenal.
Aquí están mis casos de prueba.
unset var; is-var-set 1 # var unset
var=''; is-var-set 2 # var[0] set to ''
var=foo; is-var-set 3 # var[0] set to 'foo'
var=(); is-var-set 4 # var unset (all indices)
var=(foo); is-var-set 5 # var[0] set to 'foo'
var=([0]=foo); is-var-set 6 # var[0] set to 'foo'
var=([1]=foo); is-var-set 7 # var[0] unset, but var[1] set to 'foo'
declare -a var; is-var-set 8 # var empty, but declared as an array
declare -A var; is-var-set 9 # var empty, but declared as an associative array
declare -A var # Because is-var-set() conveniently unsets it
var=([xz]=foo); is-var-set A # var[xz] set to 'foo', but var's otherwise empty
declare -a var # Demonstrate that Bash knows about var, even when there's
declare -A var; is-var-set B # apparently no way to just _check_ its existence
Aquí está la salida.
1: var's unset. ${var+x}= ${#var[@]}=0
2: var is set. ${var+x}=x ${#var[@]}=1
3: var is set. ${var+x}=x ${#var[@]}=1
4: var's unset. ${var+x}= ${#var[@]}=0
5: var is set. ${var+x}=x ${#var[@]}=1
6: var is set. ${var+x}=x ${#var[@]}=1
7: Is var set? ${var+x}= ${#var[@]}=1
8: var's unset. ${var+x}= ${#var[@]}=0
9: var's unset. ${var+x}= ${#var[@]}=0
A: Is var set? ${var+x}= ${#var[@]}=1
./foo.sh: line 26: declare: var: cannot convert indexed to associative array
B: var's unset. ${var+x}= ${#var[@]}=0
En suma:
-
${var+x}
la sintaxis de expansión de parámetros funciona tan bien como la sintaxis de matriz${#var[@]}
en la mayoría de los casos, como la comprobación de parámetros a funciones. La única forma en que este caso podría romperse es si una versión futura de Bash agrega una forma de pasar matrices a funciones sin convertir el contenido en argumentos individuales. - Se requiere sintaxis de matriz para matrices no vacías (asociativo o no) con elemento
0
unset. - Ninguna sintaxis explica lo que está pasando si
declare -a var
se ha utilizado sin asignar ni siquiera un valor null en algún lugar de la matriz. Bash todavía distingue el caso en alguna parte (como se ve en testB
arriba), por lo que esta respuesta no es infalible. Afortunadamente, Bash convierte las variables de entorno exportadas en cadenas cuando se ejecuta un programa / script, por lo que cualquier problema con las variables declaradas pero no establecidas se contendrá en un solo script, al menos si no aprovisionamiento de otros scripts.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-15 14:32:17
Si desea probar que una variable está enlazada o no, esto funciona bien, incluso después de haber activado la opción nounset:
set -o noun set
if printenv variableName >/dev/null; then
# variable is bound to a value
else
# variable is unbound
fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-25 20:08:04
Me gustan las funciones auxiliares para ocultar los detalles crudos de bash. En este caso, hacerlo añade aún más crudeza (oculta):
# The first ! negates the result (can't use -n to achieve this)
# the second ! expands the content of varname (can't do ${$varname})
function IsDeclared_Tricky
{
local varname="$1"
! [ -z ${!varname+x} ]
}
Debido a que primero tuve errores en esta implementación (inspirado por las respuestas de Jens y Lionel), se me ocurrió una solución diferente:
# Ask for the properties of the variable - fails if not declared
function IsDeclared()
{
declare -p $1 &>/dev/null
}
Encuentro que es más sencillo, más grosero y más fácil de entender/recordar. El caso de prueba muestra que es equivalente:
function main()
{
declare -i xyz
local foo
local bar=
local baz=''
IsDeclared_Tricky xyz; echo "IsDeclared_Tricky xyz: $?"
IsDeclared_Tricky foo; echo "IsDeclared_Tricky foo: $?"
IsDeclared_Tricky bar; echo "IsDeclared_Tricky bar: $?"
IsDeclared_Tricky baz; echo "IsDeclared_Tricky baz: $?"
IsDeclared xyz; echo "IsDeclared xyz: $?"
IsDeclared foo; echo "IsDeclared foo: $?"
IsDeclared bar; echo "IsDeclared bar: $?"
IsDeclared baz; echo "IsDeclared baz: $?"
}
main
El caso de prueba también muestra que local var
hace NO declarar var (a menos que vaya seguido de '='). Durante bastante tiempo pensé que declaraba variables de esta manera, solo para descubrir ahora que simplemente expresaba mi intención... Es un no-op, supongo.
IsDeclared_Tricky xyz: 1
IsDeclared_Tricky foo: 1
IsDeclared_Tricky bar: 0
IsDeclared_Tricky baz: 0
IsDeclared xyz: 1
Es declarado foo: 1
IsDeclared bar: 0
IsDeclared baz: 0
BONO: usecase
Utilizo principalmente esto prueba para dar (y devolver) parámetros a las funciones de una manera algo "elegante" y segura (casi se asemeja a una interfaz...):
#auxiliary functions
function die()
{
echo "Error: $1"; exit 1
}
function assertVariableDeclared()
{
IsDeclared "$1" || die "variable not declared: $1"
}
function expectVariables()
{
while (( $# > 0 )); do
assertVariableDeclared $1; shift
done
}
# actual example
function exampleFunction()
{
expectVariables inputStr outputStr
outputStr="$inputStr world!"
}
function bonus()
{
local inputStr='Hello'
local outputStr= # remove this to trigger error
exampleFunction
echo $outputStr
}
bonus
Si se llama con todas las variables requires declaradas:
Hola mundo!
Else:
Error: variable no declarada: outputStr
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-01 13:23:29
Funciones para comprobar si la variable está declarada/desajustada
Incluido vacío $array=()
Las siguientes funciones prueban si el nombre dado existe como variable
# The first parameter needs to be the name of the variable to be checked.
# (See example below)
var_is_declared() {
{ [[ -n ${!1+anything} ]] || declare -p $1 &>/dev/null;}
}
var_is_unset() {
{ [[ -z ${!1+anything} ]] && ! declare -p $1 &>/dev/null;}
}
- Al probar primero si la variable está (des)establecida, se puede evitar la llamada a declarar, si no es necesario.
- Si sin embargo
$1
contiene el nombre de un$array=()
vacío, la llamada a declarar se aseguraría de obtener el resultado correcto - Nunca hay muchos datos pasados a / dev / null como declare es solo se llama si la variable no está establecida o si es una matriz vacía.
Estas funciones probarían como se muestra en las siguientes condiciones:
a; # is not declared a=; # is declared a="foo"; # is declared a=(); # is declared a=(""); # is declared unset a; # is not declared a; # is unset a=; # is not unset a="foo"; # is not unset a=(); # is not unset a=(""); # is not unset unset a; # is unset
.
Para más detalles
Y un script de prueba ver mi respuesta a la pregunta "¿Cómo compruebo si existe una variable en bash?".
Observación: El uso similar dedeclare -p
, como también se muestra en Peregring-lk 's respuesta , es realmente coincidencia. ¡De lo contrario, por supuesto, lo habría acreditado!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:03
case "$1" in
"") echo "blank";;
*) echo "set"
esac
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-30 15:32:16