if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi.
Jens
211
Nota para los buscadores de soluciones: Hay muchas respuestas altamente calificadas a esta pregunta que responden la pregunta "es variable no vacía". Las soluciones de corrección más ("es un conjunto variable") se mencionan en las respuestas de Jens y Lionel a continuación.
Nathan Kidd
8
También Russell Harmon y Seamus están en lo correcto con su -vprueba, aunque aparentemente esto solo está disponible en nuevas versiones bashy no es portátil en todos los shells.
Graeme
55
Como señaló @NathanKidd, Lionel y Jens dan las soluciones correctas. prosseek, debe cambiar su respuesta aceptada a una de estas.
Garrett
3
... o la respuesta incorrecta podría ser rechazada por los más exigentes entre nosotros, ya que @prosseek no está abordando el problema.
dan3
Respuestas:
2305
(Por lo general) la forma 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ámetros que se evalúa como nada si no varestá establecida, y sustituye la cadena de lo xcontrario
Digresión de cotizaciones
Las citas se pueden omitir (por lo que podemos decir en ${var+x}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 palabras, por lo que no necesita comillas) o nada (lo que da como resultado [ -z ], que convenientemente se evalúa al mismo valor (verdadero) que también lo [ -z "" ]hace)).
Sin embargo, si bien las citas se pueden omitir de manera segura, y no fue inmediatamente obvio para todos (ni siquiera fue evidente para el primer autor de esta explicación de citas que también es un codificador principal de Bash), a veces sería mejor escribir la solución con comillas como [ -z "${var+x}" ], al muy bajo costo posible de una penalización de velocidad O (1). El primer autor también agregó esto como un comentario al lado del código usando esta solución que proporciona la URL a esta respuesta, que ahora también incluye la explicación de por qué las citas pueden omitirse de manera 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 se establece 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 al no especificarlas se predetermina a 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.
@Garrett, su edición ha hecho que esta respuesta sea incorrecta, ${var+x}es la sustitución correcta para usar. El uso [ -z ${var:+x} ]no produce un resultado diferente que [ -z "$var" ].
Graeme
11
Esto no funciona Obtengo "no establecido" independientemente de si var está establecido en un valor o no (borrado con "unset var", "echo $ var" no produce salida).
Brent212
10
Para la sintaxis de la solución $ {parámetro + palabra}, la sección del manual oficial es gnu.org/software/bash/manual/… ; sin embargo, un error en eso, no menciona muy claramente esta sintaxis, pero dice solo una cita (Omitir los dos puntos [":"] da como resultado una prueba solo para un parámetro que no está establecido ... $ {parámetro: + palabra} [significa] Si el parámetro es nulo o no establecido, no se sustituye nada; de lo contrario, se sustituye la expansión de la palabra); la referencia citada pubs.opengroup.org/onlinepubs/9699919799/utilities/… (bueno saber) tiene documentos mucho más claros aquí.
Destiny Architect
77
Parece que se requieren comillas cuando usa varias expresiones, por ejemplo, [ -z "" -a -z ${var+x} ]obtienebash: [: argument expected en bash 4.3-ubuntu (pero no, por ejemplo, zsh). Realmente no me gusta la respuesta usando una sintaxis que funciona en algunos casos.
FauxFaux
41
Usar un simple [ -z $var ]no es más "incorrecto" que omitir comillas. De cualquier manera, estás haciendo suposiciones sobre tu aporte. Si está bien tratar una cadena vacía como no establecida, [ -z $var ]es todo lo que necesita.
nshew
910
Para verificar la variable de cadena no nula / no nula, es decir, si está establecida, use
if[-n "$1"]
Es lo contrario de -z. Me encuentro usando -nmás de -z.
Lo usarías como:
if[-n "$1"];then
echo "You supplied the first parameter!"else
echo "First parameter not supplied."fi
Por lo general, prefiero [[ ]]sobre [ ], ya que [[ ]]es más poderoso y causa menos problemas en ciertas situaciones (vea esta pregunta para obtener una explicación de la diferencia entre los dos). La pregunta específicamente pide una solución bash y no menciona ningún requisito de portabilidad.
Flujo
18
La pregunta es cómo se puede ver si se establece una variable . Entonces no puede suponer que la variable está establecida.
Hola
77
Estoy de acuerdo, []funciona mejor especialmente para los scripts de shell (no bash).
Hengjie
73
Falla en set -u.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
63
Tenga en cuenta que -nes la prueba predeterminada, por lo que es más simple [ "$1" ]o [[ $1 ]]funciona también. También tenga en cuenta que con las [[ ]]citas es innecesario .
TNE
479
Aquí le mostramos cómo probar si un parámetro no está configurado , está vacío ("Nulo") o está configurado con un valor :
+--------------------+----------------------+-----------------+-----------------+|Expression| parameter | parameter | parameter ||in script:|Set and NotNull|SetButNull|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 |+--------------------+----------------------+-----------------+-----------------+
En todos los casos que se muestran con "sustituto", la expresión se reemplaza con el valor mostrado. En todos los casos que se muestran con "asignar", al parámetro se le asigna ese valor, que también reemplaza la expresión.
Para mostrar esto en acción:
+--------------------+----------------------+-----------------+-----------------+|Expression| FOO="world"| FOO=""| unset FOO ||in script:|(Set and NotNull)|(SetButNull)|(Unset)|+--------------------+----------------------+-----------------+-----------------+| ${FOO:-hello}| world | hello | hello || ${FOO-hello}| world |""| hello || ${FOO:=hello}| world | FOO=hello | FOO=hello || ${FOO=hello}| world |""| FOO=hello || ${FOO:?hello}| world | error, exit | error, exit || ${FOO?hello}| world |""| error, exit || ${FOO:+hello}| hello |""|""|| ${FOO+hello}| hello | hello |""|+--------------------+----------------------+-----------------+-----------------+
@HelloGoodbye Sí, funciona: set foo; echo ${1:-set but null or unset}echos "foo"; set --; echo ${1:-set but null or unset}ecos establecidos pero nulos ...
Jens
44
@HelloGoodbye Los parámetros posicionales se pueden establecer con, uh, set:-)
Jens
95
Esta respuesta es muy confusa. ¿Algún ejemplo práctico sobre cómo usar esta tabla?
Ben Davis
12
@BenDavis Los detalles se explican en el enlace al estándar POSIX, que hace referencia al capítulo del que se toma la tabla. Una construcción que uso en casi cualquier script que escribo es : ${FOOBAR:=/etc/foobar.conf}establecer un valor predeterminado para una variable si no está establecida o es nula.
Jens
1
parameteres cualquier nombre de variable. wordes una cadena a sustituir según la sintaxis de la tabla que está utilizando y si la variable $parameterestá establecida, establecida pero nula o sin establecer. ¡No para complicar las cosas, sino wordque también puede incluir variables! Esto puede ser muy útil para pasar argumentos opcionales separados por un carácter. Por ejemplo: ${parameter:+,${parameter}}genera una coma separada ,$parametersi está establecida pero no es nula. En este caso, wordes,${parameter}
TrinitronX
260
Si bien la mayoría de las técnicas indicadas aquí son correctas, bash 4.2 admite una prueba real de la presencia de una variable ( man bash ), en lugar de probar el valor de la variable.
Notablemente, este enfoque no causará un error cuando se usa para verificar una variable no establecida en set -u/ set -o nounsetmode, a diferencia de muchos otros enfoques, como el uso [ -z.
En bash 4.1.2, independientemente de si la variable está configurada, [[ -v aaa ]]; echo $?==>-bash: conditional binary operator expected-bash: syntax error near 'aaa'
Dan
32
El argumento '-v' para la construcción 'test' se agregó en bash 4.2.
Ti Strga
19
Se agregó el argumento -v como complemento de la opción de shell -u (conjunto de sustantivos). Con 'nounset' activado (set -u), el shell devolverá un error y finalizará, si no es interactivo. $ # fue bueno para verificar los parámetros posicionales. Sin embargo, las variables con nombre se necesitaban de otra manera, además del clobbering, para identificarlas como no establecidas. Es lamentable que esta característica haya llegado tan tarde porque muchos están obligados a ser compatibles con versiones anteriores, en cuyo caso no pueden usarla. La única otra opción es usar trucos o 'hacks' para evitarlo como se muestra arriba, pero es muy poco elegante.
osirisgothra
2
Tenga en cuenta que esto no funciona para las variables que se declaran pero no se establecen. por ejemplodeclare -a foo
miken32
17
Es por eso que sigo leyendo después de la respuesta aceptada / mejor votada.
Joe
176
Hay muchas maneras de hacer esto, siendo las siguientes una de ellas:
if[-z "$1"]
Esto tiene éxito si $ 1 es nulo o no está establecido
Hay una diferencia entre un parámetro no establecido y un parámetro con un valor nulo.
chepner
21
Solo quiero ser pedante y señalar que esta es la respuesta opuesta a lo que plantea la pregunta. Las preguntas preguntan si la variable está establecida, no si la variable no está establecida.
Philluminati
47
[[ ]]no es más que una trampa de portabilidad. if [ -n "$1" ]debería usarse aquí.
Jens
73
Esta respuesta es incorrecta. La pregunta pide una manera de saber si una variable está configurada, no si está configurada en un valor no vacío. Dado foo="", $footiene un valor, pero -zsimplemente informará que está vacío. Y -z $fooexplotará si tienes set -o nounset.
Keith Thompson
44
Depende de la definición de "variable establecida". Si desea verificar si la variable está establecida en una cadena distinta de cero , la respuesta de mbranning es correcta. Pero si desea verificar si la variable se declara pero no se inicializa (es decir foo=), la respuesta de Russel es correcta.
Flujo
77
Siempre encuentro que la tabla POSIX en la otra respuesta es lenta para asimilar, así que aquí está mi opinión:
Tenga en cuenta que cada grupo (con y sin precedentes de colon) tiene el mismo conjunto y no definidas casos, por lo que lo único que difiere es la forma en la vacía se manejan casos.
Con los dos puntos anteriores, los casos vacíos y no definidos son idénticos, por lo que usaría aquellos donde sea posible (es decir :=, usar , no solo= , porque el caso vacío es incompatible).
Encabezados:
establecer medios VARIABLEno está vacío (VARIABLE="something" )
medios vacíosVARIABLE está vacío / nulo (VARIABLE="" )
los medios VARIABLEno establecidos no existen ( 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 que el resultado es nulo (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.
Solucionó solo los que son errores de codificación reales (instancias de indirección no deseada al trabajar con variables). Hice una edición para corregir algunos casos más en los que el dólar marca la diferencia al interpretar la descripción. Por cierto, todas las variables de shell (con la excepción de las matrices) son variables de cadena; Puede suceder que contengan una cadena que se pueda interpretar como un número. Hablar de cuerdas solo empaña el mensaje. Las citas no tienen nada que ver con las cadenas, son solo una alternativa para escapar. VARIABLE=""podría escribirse como VARIABLE=. Aún así, el primero es más legible.
Palec
Gracias por la tabla, es muy útil, sin embargo, estoy tratando de que la secuencia de comandos salga si está desarmado o vacío. Pero el código de salida que obtengo es 1, no 127.
Astronauta
64
Para ver si una variable no está vacía, uso
if[[ $var ]];then...# `$var' expands to a nonempty string
Lo contrario prueba si una variable está desarmada 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), uso
if[[ ${var+x}]];then...# `var' exists (empty or nonempty)if[[ ${1+x}]];then...# Parameter 1 exists (empty or nonempty)
Lo contrario prueba si una variable no está establecida:
if[[! ${var+x}]];then...# `var' is not set at allif[[! ${1+x}]];then...# We were called with no arguments
Yo también he estado usando esto por un tiempo; solo de manera reducida:[ $isMac ] && param="--enable-shared"
@Bhaskar Creo que es porque esta respuesta ya proporcionó esencialmente la misma respuesta (se usa ${variable+x}para obtener xiff $variable) casi medio año antes. También tiene muchos más detalles que explican por qué es correcto.
Mark Haferkamp
pero ${variable+x}es menos legible (y obvio)
knocte
35
En una versión moderna de Bash (4.2 o posterior, creo; no estoy seguro), intentaría esto:
if[!-v SOMEVARIABLE ]#note the lack of a $ sigilthen
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
También tenga en cuenta que [ -v "$VARNAME" ]no es incorrecto, sino que simplemente realiza una prueba diferente. Supongamos VARNAME=foo; luego comprueba si hay una variable llamada fooque se establece.
chepner
55
Nota para aquellos que desean portabilidad, -vno es compatible con POSIX
kzh
Si se obtiene [: -v: unexpected operator, hay que asegurarse de usar en bashlugar de sh.
koppor
25
if["$1"!=""];then
echo \$1 is setelse
echo \$1 is not setfi
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 setelse
echo \$1 is not setfi
La primera prueba es al revés; Creo que quieres [ "$1" != "" ](o [ -n "$1" ]) ...
Gordon Davisson
10
Esto fallará si $1se establece en la cadena vacía.
Hola
2
La segunda parte de la respuesta (parámetros de conteo) es una solución útil para la primera parte de la respuesta que no funciona cuando $1se establece en una cadena vacía.
Mark Berry
Esto fallará si set -o nounsetestá activado.
Flimm
21
Nota
Estoy dando una respuesta muy centrada en Bash debido a la bashetiqueta.
Respuesta corta
Siempre que solo se trate de variables con nombre en Bash, esta función siempre debería decirle si la variable se ha configurado, incluso si se trata de una matriz vacía.
variable-is-set(){
declare -p "$1"&>/dev/null
}
Por que esto funciona
En Bash (al menos desde 3.0), si vares una variable declarada / establecida, declare -p vargenera un declarecomando que establecería la variable varsea cual sea su tipo y valor actuales, y devuelve el código de estado 0(éxito). Si varno está declarado, declare -p varenvía un mensaje de error stderry devuelve el código de estado 1. Usando &>/dev/null, redirige tanto regular stdoutcomostderr salida a/dev/null , nunca se verá, y sin cambiar el código de estado. Por lo tanto, la función solo devuelve el código de estado.
¿Por qué otros métodos (a veces) fallan en Bash
[ -n "$var" ]: Esto solo comprueba si ${var[0]}no está vacío. (En Bash, $vares lo mismo que ${var[0]}).
[ -n "${var+x}" ]: Esto solo verifica si ${var[0]}está configurado.
[ "${#var[@]}" != 0 ]: Esto solo comprueba si se establece al menos un índice de $var.
Cuando este método falla en Bash
Esto sólo funciona para las variables con nombre (incluidos $_), no ciertas variables especiales ( $!, $@, $#, $$, $*, $?, $-, $0, $1, $2, ..., y ninguno de los que puede haber olvidado). Como ninguno de estos son matrices, el estilo POSIX [ -n "${var+x}" ]funciona para todas estas variables especiales. Pero tenga cuidado de incluirlo en una función ya que muchas variables especiales cambian los valores / existencia cuando se llaman funciones.
Nota de compatibilidad de shell
Si su script tiene matrices y está tratando de hacerlo compatible con la mayor cantidad posible de shells, entonces considere usar en typeset -plugar de declare -p. He leído que ksh solo es compatible con el primero, pero no he podido probar esto. Sé que Bash 3.0+ y Zsh 5.5.1 son compatibles con ambos typeset -py declare -psolo difieren en cuál es una alternativa para el otro. Pero no he probado las diferencias más allá de esas dos palabras clave, y no he probado otros shells.
Si necesita que su script sea compatible con POSIX sh, no puede usar matrices. Sin matrices, [ -n "{$var+x}" ]funciona.
Código de comparación para diferentes métodos en Bash
Esta función desarma la variable var, evals el código pasado, ejecuta pruebas para determinar si varestá establecida por el evalcódigo d, y finalmente muestra los códigos de estado resultantes para las diferentes pruebas.
Estoy omitiendo test -v var, [ -v var ]y [[ -v var ]]porque producen resultados idénticos al estándar POSIX [ -n "${var+x}" ], al tiempo que requieren Bash 4.2+. También estoy omitiendo typeset -pporque es lo mismo que declare -pen los shells que he probado (Bash 3.0 a 5.0 y Zsh 5.5.1).
is-var-set-after(){# Set var by passed expression.
unset var
eval"$1"# Run the tests, in increasing order of accuracy.[-n "$var"]# (index 0 of) var is nonempty
nonempty=$?[-n "${var+x}"]# (index 0 of) var is set, maybe empty
plus=$?["${#var[@]}"!=0]# var has at least one index set, maybe empty
count=$?
declare -p var &>/dev/null # var has been declared (any type)
declared=$?# Show test results.
printf '%30s: %2s %2s %2s %2s\n'"$1" $nonempty $plus $count $declared
}
Código de caso de prueba
Tenga en cuenta que los resultados de la prueba pueden ser inesperados debido a que Bash trata los índices de matriz no numéricos como "0" si la variable no se ha declarado como una matriz asociativa. Además, las matrices asociativas solo son válidas en Bash 4.0+.
# Header.
printf '%30s: %2s %2s %2s %2s\n'"test"'-n''+x''#@''-p'# First 5 tests: Equivalent to setting 'var=foo' because index 0 of an# indexed array is also the nonindexed value, and non-numerical# indices in an array not declared as associative are the same as# index 0.
is-var-set-after "var=foo"# 0 0 0 0
is-var-set-after "var=(foo)"# 0 0 0 0
is-var-set-after "var=([0]=foo)"# 0 0 0 0
is-var-set-after "var=([x]=foo)"# 0 0 0 0
is-var-set-after "var=([y]=bar [x]=foo)"# 0 0 0 0# '[ -n "$var" ]' fails when var is empty.
is-var-set-after "var=''"# 1 0 0 0
is-var-set-after "var=([0]='')"# 1 0 0 0# Indices other than 0 are not detected by '[ -n "$var" ]' or by# '[ -n "${var+x}" ]'.
is-var-set-after "var=([1]='')"# 1 1 0 0
is-var-set-after "var=([1]=foo)"# 1 1 0 0
is-var-set-after "declare -A var; var=([x]=foo)"# 1 1 0 0# Empty arrays are only detected by 'declare -p'.
is-var-set-after "var=()"# 1 1 1 0
is-var-set-after "declare -a var"# 1 1 1 0
is-var-set-after "declare -A var"# 1 1 1 0# If 'var' is unset, then it even fails the 'declare -p var' test.
is-var-set-after "unset var"# 1 1 1 1
Prueba de salida
Los mnemónicos de ensayo en la fila de cabecera corresponden a [ -n "$var" ], [ -n "${var+x}" ], [ "${#var[@]}" != 0 ], y declare -p var, respectivamente.
declare -p var &>/dev/null es (100%?) confiable para probar variables con nombre en Bash desde al menos 3.0.
[ -n "${var+x}" ] es confiable en situaciones compatibles con POSIX, pero no puede manejar matrices.
Existen otras pruebas para verificar si una variable no está vacía y para verificar las variables declaradas en otros shells. Pero estas pruebas no son adecuadas para las secuencias de comandos Bash ni POSIX.
De las respuestas que probé, esta ( declare -p var &>/dev/null) es la ÚNICA que funciona. ¡GRACIAS!
user1387866
2
@ mark-haferkamp Intenté editar su respuesta para agregar el "/" precedente crítico a su código de función para que se lea, ... &> /dev/nullpero SO no me permitió hacer una edición de un solo carácter 🙄 (debe ser> 6 caracteres, incluso intenté agregar espacios en blanco Pero no funcionó). Además, puede valer la pena cambiar la función para cambiar $1una muestra llamada variable (p OUTPUT_DIR. Ej. ) Ya que, como señaló, las variables especiales como $1no funcionan aquí. De todos modos, es una edición crítica, de lo contrario, el código está buscando crear un archivo llamado nullen un directorio relativo llamado dev. Por cierto, ¡gran respuesta!
joehanna
Además, usar el nombre de la variable sin el prefijo $ también funciona: declare -p PATH &> /dev/nulldevuelve 0 donde como declare -p ASDFASDGFASKDF &> /dev/nulldevuelve 1. (en bash 5.0.11 (1) -release)
joehanna
1
¡Buen trabajo! 1 palabra de precaución: declare vardeclara var una variable pero no la establece en términos de set -o nounset: Prueba condeclare foo bar=; set -o nounset; echo $bar; echo $foo
xebeche
@joehanna ¡Gracias por descubrir lo que falta /! Lo arreglé, pero creo que la lógica es lo suficientemente confusa como para garantizar una función, especialmente a la luz del comentario de @ xebeche. @xebeche Eso es un inconveniente para mi respuesta ... Parece que tendré que intentar algo como declare -p "$1" | grep =o test -v "$1".
Mark Haferkamp
19
Para aquellos que buscan verificar si están desarmados o vacíos cuando están en un script con set -u:
if[-z "${var-}"];then
echo "Must provide var environment variable. Exiting...."
exit 1fi
La [ -z "$var" ]comprobación regular fallará con var; unbound variableif set -upero se [ -z "${var-}" ]expande a una cadena vacía si no varse establece sin fallar.
Te falta un colon. Debería ser ${var:-}, no ${var-}. Pero en Bash, puedo confirmar que funciona incluso sin el colon.
Palec
3
${var:-}y ${var-}significan cosas diferentes. ${var:-}se expandirá para vaciar cadena si vardesarmar o nula y ${var-}se expandirá a sólo si desarmar cadena vacía.
RubenLaguna
Acabo de aprender algo nuevo, gracias! Omitir los dos puntos da como resultado una prueba solo para un parámetro que no está establecido. Dicho de otra manera, si se incluyen los dos puntos, el operador comprueba la existencia de ambos parámetros y que su valor no es nulo; si se omiten los dos puntos, el operador solo prueba la existencia. Aquí no hay diferencia, pero es bueno saberlo.
Palec
17
Desea salir si no está configurado
Esto funcionó para mí. Quería que mi script salga con un mensaje de error si no se configuró un parámetro.
#!/usr/bin/env bashset-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 vuelve 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
Marque solo, sin salida - Vacío y desarmado son inválidos
Pruebe esta opción si solo desea verificar si el valor establecido = VÁLIDO o unset / empty = INVALID.
Para verificar si una variable está configurada con un valor no vacío, use [ -n "$x" ], como ya lo 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á configurada. Pero puede distinguir los dos si lo necesita: [ -n "${x+set}" ](se "${x+set}"expande a setsi xestá configurado y a la cadena vacía si no xestá configurado).
Para verificar 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) (vea la respuesta de Paul ).
Lea la sección "Expansión de parámetros" de la bashpágina del manual. La expansión de parámetros no proporciona una prueba general para establecer una variable, pero hay varias cosas que puede hacer con un parámetro si no está configurado.
Por ejemplo:
function a {
first_arg=${1-foo}# rest of the function}
se establecerá first_argigual a $1si está asignado, de lo contrario, utiliza el valor "foo". Si aabsolutamente debe tomar un solo parámetro, y no existe un buen valor predeterminado, puede salir con un mensaje de error cuando no se proporciona ningún parámetro:
function a {: ${1?a must take a single argument}# rest of the function}
(Tenga en cuenta el uso de :como un comando nulo, que solo expande los valores de sus argumentos. No queremos hacer nada $1en este ejemplo, simplemente salga si no está configurado)
Usar [[ -z "$var" ]]es la forma más fácil de saber si una variable se configuró o no, pero esa opción -zno distingue entre una variable no establecida y una variable establecida en una cadena vacía:
Las respuestas anteriores no funcionan cuando la opción Bash set -uestá habilitada. Además, no son dinámicos, por ejemplo, ¿cómo se define la variable de prueba con el nombre "dummy"? Prueba esto:
is_var_defined(){if[ $# -ne 1 ]then
echo "Expected exactly one argument: variable name as string, e.g., 'my_var'"
exit 1fi# 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.}
que necesita entre comillas $1, es decir, [ ! -z "$1" ]. O puede escribir [[ ! -z $1 ]]en bash / ksh / zsh.
Gilles 'SO- deja de ser malvado'
55
Esto fallará si $1se establece en la cadena vacía.
Hola
4
Mi forma preferida es esta:
$ var=10
$ if! ${var+false};then echo "is set";else echo "NOT set";fi
is set
$ unset -v var
$ if! ${var+false};then echo "is set";else echo "NOT set";fi
NOT set
Básicamente, si se establece una variable, se convierte en "una negación de lo resultante false" (lo que será true= "se establece").
Y, si no está establecido, se convertirá en "una negación de lo resultante true" (como se evalúa el resultado vacío true) (así terminará como false= = NO establecido ").
if[[ ${1:+isset}]]then echo "It was set and not null.">&2else echo "It was not set or it was null.">&2fiif[[ ${1+isset}]]then echo "It was set but might be null.">&2else echo "It was was not set.">&2fi
Bienvenido a StackOverflow. Si bien su respuesta es apreciada, es mejor dar más que solo código. ¿Podría agregar un razonamiento a su respuesta o una pequeña explicación? Vea esta página para otras ideas sobre cómo expandir su respuesta.
Celeo
0
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 en Linux y Solaris hasta bash 3.0.
Desde Bash 2.0+ la expansión indirecta está disponible. Puede reemplazar el largo y complejo (con una evaluación también incluida) test -n "$(eval "echo "\${${1}+x}"")"por el equivalente:[[ ${!1+x} ]]
0
Me gustan las funciones auxiliares para ocultar los detalles crudos de bash. En este caso, hacerlo agrega 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})functionIsDeclared_Tricky{local varname="$1"![-z ${!varname+x}]}
Como tuve errores por primera vez en esta implementación (inspirada en las respuestas de Jens y Lionel), se me ocurrió una solución diferente:
# Ask for the properties of the variable - fails if not declaredfunctionIsDeclared(){
declare -p $1 &>/dev/null
}
Me parece más directo, más tímido 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 varno NO declaran var (a menos que seguido por '='). Durante bastante tiempo pensé que declaraba las variables de esta manera, solo para descubrir ahora que simplemente expresé mi intención ... Supongo que no funciona.
no funcionará cuando tenga set -uen efecto lo que imprimirá el unboud variableerror
Michael Heuberger
0
Resumen
Use test -n "${var-}"para verificar si la variable no está vacía (y por lo tanto debe definirse / establecerse también)
Use test ! -z "${var+}"para verificar si la variable está definida / establecida (incluso si está vacía)
Tenga en cuenta que el primer caso de uso es mucho más común en los scripts de shell y esto es lo que generalmente querrá usar.
Notas
Esta solución debería funcionar en todos los shells POSIX (sh, bash, zsh, ksh, dash)
Algunas de las otras respuestas a esta pregunta son correctas, pero pueden ser confusas para las personas sin experiencia en la creación de scripts de shell, por lo que quería proporcionar una respuesta TLDR que sea menos confusa para esas personas.
Explicación
Para comprender cómo funciona esta solución, debe comprender el comando POSIXtest y la expansión ( especificación ) del parámetro de shell POSIX , así que cubramos los conceptos básicos necesarios para comprender la respuesta.
El comando de prueba evalúa una expresión y devuelve verdadero o falso (a través de su estado de salida). El operador -ndevuelve verdadero si el operando es una cadena no vacía. Entonces, por ejemplo, test -n "a"devuelve verdadero, mientras que test -n ""devuelve falso. Ahora, para verificar si una variable no está vacía (lo que significa que debe definirse), puede usarla test -n "$var". Sin embargo, algunos scripts de shell tienen una opción set ( set -u) que hace que cualquier referencia a variables indefinidas emita un error, por lo que si la variable varno está definida, la expresión $acausará un error. Para manejar este caso correctamente, debe usar la expansión de variables, que le indicará al shell que reemplace la variable con una cadena alternativa si no está definida, evitando el error mencionado anteriormente.
La expansión de la variable ${var-}significa: si la variable varno está definida (también llamada "no establecida"), reemplácela con una cadena vacía. Por test -n "${var-}"lo tanto , devolverá verdadero si $varno está vacío, que es casi siempre lo que desea verificar en los scripts de shell. La verificación inversa, si $varno está definida o no está vacía, sería test -z "${var-}".
Ahora al segundo caso de uso: verificar si la variable varestá definida, ya sea vacía o no. Este es un caso de uso menos común y un poco más complejo, y le recomendaría que lea la excelente respuesta de Lionels para comprenderla mejor.
Creo que quieres decir set -o nounset, no set -o noun set. Esto solo funciona para variables que han sido exporteditadas. También cambia su configuración de una manera que es difícil de deshacer.
if test $# -gt 0; then printf 'arg <%s>\n' "$@"; fi
.-v
prueba, aunque aparentemente esto solo está disponible en nuevas versionesbash
y no es portátil en todos los shells.Respuestas:
(Por lo general) la forma correcta
donde
${var+x}
es una expansión de parámetros que se evalúa como nada si novar
está establecida, y sustituye la cadena de lox
contrarioDigresión de cotizaciones
Las citas se pueden omitir (por lo que podemos decir en
${var+x}
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 ax
(que no contiene saltos de palabras, por lo que no necesita comillas) o nada (lo que da como resultado[ -z ]
, que convenientemente se evalúa al mismo valor (verdadero) que también lo[ -z "" ]
hace)).Sin embargo, si bien las citas se pueden omitir de manera segura, y no fue inmediatamente obvio para todos (ni siquiera fue evidente para el primer autor de esta explicación de citas que también es un codificador principal de Bash), a veces sería mejor escribir la solución con comillas como
[ -z "${var+x}" ]
, al muy bajo costo posible de una penalización de velocidad O (1). El primer autor también agregó esto como un comentario al lado del código usando esta solución que proporciona la URL a esta respuesta, que ahora también incluye la explicación de por qué las citas pueden omitirse de manera segura.(A menudo) El camino equivocado
Esto a menudo es incorrecto porque no distingue entre una variable que no está establecida y una variable que se establece 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 al no especificarlas se predetermina a 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.fuente
${var+x}
es la sustitución correcta para usar. El uso[ -z ${var:+x} ]
no produce un resultado diferente que[ -z "$var" ]
.[ -z "" -a -z ${var+x} ]
obtienebash: [: argument expected
en bash 4.3-ubuntu (pero no, por ejemplo, zsh). Realmente no me gusta la respuesta usando una sintaxis que funciona en algunos casos.[ -z $var ]
no es más "incorrecto" que omitir comillas. De cualquier manera, estás haciendo suposiciones sobre tu aporte. Si está bien tratar una cadena vacía como no establecida,[ -z $var ]
es todo lo que necesita.Para verificar la variable de cadena no nula / no nula, es decir, si está establecida, use
Es lo contrario de
-z
. Me encuentro usando-n
más de-z
.Lo usarías como:
fuente
[[ ]]
sobre[ ]
, ya que[[ ]]
es más poderoso y causa menos problemas en ciertas situaciones (vea esta pregunta para obtener una explicación de la diferencia entre los dos). La pregunta específicamente pide una solución bash y no menciona ningún requisito de portabilidad.[]
funciona mejor especialmente para los scripts de shell (no bash).set -u
.-n
es la prueba predeterminada, por lo que es más simple[ "$1" ]
o[[ $1 ]]
funciona también. También tenga en cuenta que con las[[ ]]
citas es innecesario .Aquí le mostramos cómo probar si un parámetro no está configurado , está vacío ("Nulo") o está configurado con un valor :
Fuente: POSIX: Expansión de parámetros :
Para mostrar esto en acción:
fuente
set foo; echo ${1:-set but null or unset}
echos "foo";set --; echo ${1:-set but null or unset}
ecos establecidos pero nulos ...set
:-): ${FOOBAR:=/etc/foobar.conf}
establecer un valor predeterminado para una variable si no está establecida o es nula.parameter
es cualquier nombre de variable.word
es una cadena a sustituir según la sintaxis de la tabla que está utilizando y si la variable$parameter
está establecida, establecida pero nula o sin establecer. ¡No para complicar las cosas, sinoword
que también puede incluir variables! Esto puede ser muy útil para pasar argumentos opcionales separados por un carácter. Por ejemplo:${parameter:+,${parameter}}
genera una coma separada,$parameter
si está establecida pero no es nula. En este caso,word
es,${parameter}
Si bien la mayoría de las técnicas indicadas aquí son correctas, bash 4.2 admite una prueba real de la presencia de una variable ( man bash ), en lugar de probar el valor de la variable.
Notablemente, este enfoque no causará un error cuando se usa para verificar una variable no establecida en
set -u
/set -o nounset
mode, a diferencia de muchos otros enfoques, como el uso[ -z
.fuente
[[ -v aaa ]]; echo $?
==>-bash: conditional binary operator expected
-bash: syntax error near 'aaa'
declare -a foo
Hay muchas maneras de hacer esto, siendo las siguientes una de ellas:
Esto tiene éxito si $ 1 es nulo o no está establecido
fuente
[[ ]]
no es más que una trampa de portabilidad.if [ -n "$1" ]
debería usarse aquí.foo=""
,$foo
tiene un valor, pero-z
simplemente informará que está vacío. Y-z $foo
explotará si tienesset -o nounset
.foo=
), la respuesta de Russel es correcta.Siempre encuentro que la tabla POSIX en la otra respuesta es lenta para asimilar, así que aquí está mi opinión:
Tenga en cuenta que cada grupo (con y sin precedentes de colon) tiene el mismo conjunto y no definidas casos, por lo que lo único que difiere es la forma en la vacía se manejan casos.
Con los dos puntos anteriores, los casos vacíos y no definidos son idénticos, por lo que usaría aquellos donde sea posible (es decir
:=
, usar , no solo=
, porque el caso vacío es incompatible).Encabezados:
VARIABLE
no está vacío (VARIABLE="something"
)VARIABLE
está vacío / nulo (VARIABLE=""
)VARIABLE
no establecidos no existen (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 que el resultado es nulo (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.fuente
VARIABLE=""
podría escribirse comoVARIABLE=
. Aún así, el primero es más legible.Para ver si una variable no está vacía, uso
Lo contrario prueba si una variable está desarmada o vacía:
Para ver si se establece una variable (vacía o no vacía), uso
Lo contrario prueba si una variable no está establecida:
fuente
[ $isMac ] && param="--enable-shared"
${variable+x}
para obtenerx
iff$variable
) casi medio año antes. También tiene muchos más detalles que explican por qué es correcto.${variable+x}
es menos legible (y obvio)En una versión moderna de Bash (4.2 o posterior, creo; no estoy seguro), intentaría esto:
fuente
[ -v "$VARNAME" ]
no es incorrecto, sino que simplemente realiza una prueba diferente. SupongamosVARNAME=foo
; luego comprueba si hay una variable llamadafoo
que se establece.-v
no es compatible con POSIX[: -v: unexpected operator
, hay que asegurarse de usar enbash
lugar desh
.Aunque para los argumentos, normalmente es mejor probar $ #, que es el número de argumentos, en mi opinión.
fuente
[ "$1" != "" ]
(o[ -n "$1" ]
) ...$1
se establece en la cadena vacía.$1
se establece en una cadena vacía.set -o nounset
está activado.Nota
Estoy dando una respuesta muy centrada en Bash debido a la
bash
etiqueta.Respuesta corta
Siempre que solo se trate de variables con nombre en Bash, esta función siempre debería decirle si la variable se ha configurado, incluso si se trata de una matriz vacía.
Por que esto funciona
En Bash (al menos desde 3.0), si
var
es una variable declarada / establecida,declare -p var
genera undeclare
comando que establecería la variablevar
sea cual sea su tipo y valor actuales, y devuelve el código de estado0
(éxito). Sivar
no está declarado,declare -p var
envía un mensaje de errorstderr
y devuelve el código de estado1
. Usando&>/dev/null
, redirige tanto regularstdout
comostderr
salida a/dev/null
, nunca se verá, y sin cambiar el código de estado. Por lo tanto, la función solo devuelve el código de estado.¿Por qué otros métodos (a veces) fallan en Bash
Cuando este método falla en Bash
Esto sólo funciona para las variables con nombre (incluidos
$_
), no ciertas variables especiales ($!
,$@
,$#
,$$
,$*
,$?
,$-
,$0
,$1
,$2
, ..., y ninguno de los que puede haber olvidado). Como ninguno de estos son matrices, el estilo POSIX[ -n "${var+x}" ]
funciona para todas estas variables especiales. Pero tenga cuidado de incluirlo en una función ya que muchas variables especiales cambian los valores / existencia cuando se llaman funciones.Nota de compatibilidad de shell
Si su script tiene matrices y está tratando de hacerlo compatible con la mayor cantidad posible de shells, entonces considere usar en
typeset -p
lugar dedeclare -p
. He leído que ksh solo es compatible con el primero, pero no he podido probar esto. Sé que Bash 3.0+ y Zsh 5.5.1 son compatibles con ambostypeset -p
ydeclare -p
solo difieren en cuál es una alternativa para el otro. Pero no he probado las diferencias más allá de esas dos palabras clave, y no he probado otros shells.Si necesita que su script sea compatible con POSIX sh, no puede usar matrices. Sin matrices,
[ -n "{$var+x}" ]
funciona.Código de comparación para diferentes métodos en Bash
Esta función desarma la variable
var
,eval
s el código pasado, ejecuta pruebas para determinar sivar
está establecida por eleval
código d, y finalmente muestra los códigos de estado resultantes para las diferentes pruebas.Estoy omitiendo
test -v var
,[ -v var ]
y[[ -v var ]]
porque producen resultados idénticos al estándar POSIX[ -n "${var+x}" ]
, al tiempo que requieren Bash 4.2+. También estoy omitiendotypeset -p
porque es lo mismo quedeclare -p
en los shells que he probado (Bash 3.0 a 5.0 y Zsh 5.5.1).Código de caso de prueba
Tenga en cuenta que los resultados de la prueba pueden ser inesperados debido a que Bash trata los índices de matriz no numéricos como "0" si la variable no se ha declarado como una matriz asociativa. Además, las matrices asociativas solo son válidas en Bash 4.0+.
Prueba de salida
Los mnemónicos de ensayo en la fila de cabecera corresponden a
[ -n "$var" ]
,[ -n "${var+x}" ]
,[ "${#var[@]}" != 0 ]
, ydeclare -p var
, respectivamente.Resumen
fuente
declare -p var &>/dev/null
) es la ÚNICA que funciona. ¡GRACIAS!... &> /dev/null
pero SO no me permitió hacer una edición de un solo carácter 🙄 (debe ser> 6 caracteres, incluso intenté agregar espacios en blanco Pero no funcionó). Además, puede valer la pena cambiar la función para cambiar$1
una muestra llamada variable (pOUTPUT_DIR
. Ej. ) Ya que, como señaló, las variables especiales como$1
no funcionan aquí. De todos modos, es una edición crítica, de lo contrario, el código está buscando crear un archivo llamadonull
en un directorio relativo llamadodev
. Por cierto, ¡gran respuesta!declare -p PATH &> /dev/null
devuelve 0 donde comodeclare -p ASDFASDGFASKDF &> /dev/null
devuelve 1. (en bash 5.0.11 (1) -release)declare var
declara var una variable pero no la establece en términos deset -o nounset
: Prueba condeclare foo bar=; set -o nounset; echo $bar; echo $foo
/
! Lo arreglé, pero creo que la lógica es lo suficientemente confusa como para garantizar una función, especialmente a la luz del comentario de @ xebeche. @xebeche Eso es un inconveniente para mi respuesta ... Parece que tendré que intentar algo comodeclare -p "$1" | grep =
otest -v "$1"
.Para aquellos que buscan verificar si están desarmados o vacíos cuando están en un script con
set -u
:La
[ -z "$var" ]
comprobación regular fallará convar; unbound variable
ifset -u
pero se[ -z "${var-}" ]
expande a una cadena vacía si novar
se establece sin fallar.fuente
${var:-}
, no${var-}
. Pero en Bash, puedo confirmar que funciona incluso sin el colon.${var:-}
y${var-}
significan cosas diferentes.${var:-}
se expandirá para vaciar cadena sivar
desarmar o nula y${var-}
se expandirá a sólo si desarmar cadena vacía.Desea salir si no está configurado
Esto funcionó para mí. Quería que mi script salga con un mensaje de error si no se configuró un parámetro.
Esto vuelve con un error cuando se ejecuta
Marque solo, sin salida - Vacío y desarmado son inválidos
Pruebe esta opción si solo desea verificar si el valor establecido = VÁLIDO o unset / empty = INVALID.
O, incluso pruebas cortas ;-)
Verificar solo, sin salida - Solo vacío es inválido
Y esta es la respuesta a la pregunta. Use esto si solo desea verificar si el valor establecido / vacío = VÁLIDO o sin establecer = NO VÁLIDO.
NOTA, el "1" en "..- 1}" es insignificante, puede ser cualquier cosa (como x)
Pruebas cortas
Dedico esta respuesta a @ mklement0 (comentarios) que me retó a responder la pregunta con precisión.
Referencia http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
fuente
Para verificar si una variable está configurada con un valor no vacío, use
[ -n "$x" ]
, como ya lo 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á configurada. Pero puede distinguir los dos si lo necesita:
[ -n "${x+set}" ]
(se"${x+set}"
expande aset
six
está configurado y a la cadena vacía si nox
está configurado).Para verificar 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) (vea la respuesta de Paul ).fuente
Lea la sección "Expansión de parámetros" de la
bash
página del manual. La expansión de parámetros no proporciona una prueba general para establecer una variable, pero hay varias cosas que puede hacer con un parámetro si no está configurado.Por ejemplo:
se establecerá
first_arg
igual a$1
si está asignado, de lo contrario, utiliza el valor "foo". Sia
absolutamente debe tomar un solo parámetro, y no existe un buen valor predeterminado, puede salir con un mensaje de error cuando no se proporciona ningún parámetro:(Tenga en cuenta el uso de
:
como un comando nulo, que solo expande los valores de sus argumentos. No queremos hacer nada$1
en este ejemplo, simplemente salga si no está configurado)fuente
: ${var?message}
.En bash puedes usar
-v
dentro de la[[ ]]
construcción:fuente
Usar
[[ -z "$var" ]]
es la forma más fácil de saber si una variable se configuró o no, pero esa opción-z
no distingue entre una variable no establecida y una variable establecida en una cadena vacía:Es mejor verificarlo de acuerdo con el tipo de variable: variable env, parámetro o variable regular.
Para una variable env:
Para un parámetro (por ejemplo, para verificar la existencia del parámetro
$5
):Para una variable regular (usando una función auxiliar, para hacerlo de una manera elegante):
Notas:
fuente
Las respuestas anteriores no funcionan cuando la opción Bash
set -u
está habilitada. Además, no son dinámicos, por ejemplo, ¿cómo se define la variable de prueba con el nombre "dummy"? Prueba esto:Relacionado: En Bash, ¿cómo pruebo si una variable se define en modo "-u"?
fuente
eval "[ ! -z \${$1:-} ]"
a la evaluación indirecta:[ ! -z ${!1:-} ];
.Tu puedes hacer:
fuente
-n
y no negar el-z
.$1
, es decir,[ ! -z "$1" ]
. O puede escribir[[ ! -z $1 ]]
en bash / ksh / zsh.$1
se establece en la cadena vacía.Mi forma preferida es esta:
Básicamente, si se establece una variable, se convierte en "una negación de lo resultante
false
" (lo que serátrue
= "se establece").Y, si no está establecido, se convertirá en "una negación de lo resultante
true
" (como se evalúa el resultado vacíotrue
) (así terminará comofalse
= = NO establecido ").fuente
O
O
O
fuente
En un shell puedes usar el
-z
operador que es True si la longitud de la cadena es cero.Una línea simple para establecer el valor predeterminado
MY_VAR
si no está configurado; de lo contrario, opcionalmente puede mostrar el mensaje:fuente
fuente
$1
,$2
y hasta$N
siempre está configurado. Lo siento, esto es un fracaso.Encontré un código (mucho) mejor para hacer esto si desea verificar cualquier cosa
$@
.¿Por qué todo esto? Todo en
$@
existe en Bash, pero por defecto de blanco, asítest -z
ytest -n
podría ayudarte.Actualización: También puede contar el número de caracteres en un parámetro.
fuente
fuente
Esto es lo que uso todos los días:
Esto funciona bien en Linux y Solaris hasta bash 3.0.
fuente
test -n "$(eval "echo "\${${1}+x}"")"
por el equivalente:[[ ${!1+x} ]]
Me gustan las funciones auxiliares para ocultar los detalles crudos de bash. En este caso, hacerlo agrega aún más crudeza (oculta):
Como tuve errores por primera vez en esta implementación (inspirada en las respuestas de Jens y Lionel), se me ocurrió una solución diferente:
Me parece más directo, más tímido y más fácil de entender / recordar. El caso de prueba muestra que es equivalente:
El caso de prueba también muestra que
local var
no NO declaran var (a menos que seguido por '='). Durante bastante tiempo pensé que declaraba las variables de esta manera, solo para descubrir ahora que simplemente expresé mi intención ... Supongo que no funciona.BONIFICACIÓN: caso de uso
Principalmente uso esta prueba para dar (y devolver) parámetros a las funciones de una manera algo "elegante" y segura (casi como una interfaz ...):
Si se llama con todas las variables requeridas declaradas:
más:
fuente
Después de leer todas las respuestas, esto también funciona:
si no pone en
SOME_VAR
lugar de lo que tengo$SOME_VAR
, lo establecerá en un valor vacío;$
Es necesario que esto funcione.fuente
set -u
en efecto lo que imprimirá elunboud variable
errorResumen
test -n "${var-}"
para verificar si la variable no está vacía (y por lo tanto debe definirse / establecerse también)test ! -z "${var+}"
para verificar si la variable está definida / establecida (incluso si está vacía)Tenga en cuenta que el primer caso de uso es mucho más común en los scripts de shell y esto es lo que generalmente querrá usar.
Notas
Explicación
Para comprender cómo funciona esta solución, debe comprender el comando POSIX
test
y la expansión ( especificación ) del parámetro de shell POSIX , así que cubramos los conceptos básicos necesarios para comprender la respuesta.El comando de prueba evalúa una expresión y devuelve verdadero o falso (a través de su estado de salida). El operador
-n
devuelve verdadero si el operando es una cadena no vacía. Entonces, por ejemplo,test -n "a"
devuelve verdadero, mientras quetest -n ""
devuelve falso. Ahora, para verificar si una variable no está vacía (lo que significa que debe definirse), puede usarlatest -n "$var"
. Sin embargo, algunos scripts de shell tienen una opción set (set -u
) que hace que cualquier referencia a variables indefinidas emita un error, por lo que si la variablevar
no está definida, la expresión$a
causará un error. Para manejar este caso correctamente, debe usar la expansión de variables, que le indicará al shell que reemplace la variable con una cadena alternativa si no está definida, evitando el error mencionado anteriormente.La expansión de la variable
${var-}
significa: si la variablevar
no está definida (también llamada "no establecida"), reemplácela con una cadena vacía. Portest -n "${var-}"
lo tanto , devolverá verdadero si$var
no está vacío, que es casi siempre lo que desea verificar en los scripts de shell. La verificación inversa, si$var
no está definida o no está vacía, seríatest -z "${var-}"
.Ahora al segundo caso de uso: verificar si la variable
var
está definida, ya sea vacía o no. Este es un caso de uso menos común y un poco más complejo, y le recomendaría que lea la excelente respuesta de Lionels para comprenderla mejor.fuente
Para verificar si una var está configurada o no
fuente
$var
se establece en la cadena vacía.Si desea probar que una variable está vinculada o no, esto funciona bien, incluso después de haber activado la opción de sustantivo:
fuente
set -o nounset
, noset -o noun set
. Esto solo funciona para variables que han sidoexport
editadas. También cambia su configuración de una manera que es difícil de deshacer.