scripts script programas pasar parametros español ejemplos comandos comando bash shell variables

script - ¿Cómo comprobar si una variable está configurada en Bash?



shell script linux español (30)

Funciones para comprobar si la variable está declarada / desarmada

incluyendo vacio $array=()


Las siguientes funciones prueban si el nombre dado existe como una 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) configurada, la llamada a declarar se puede evitar, si no es necesario.
  • Sin embargo, si $1contiene el nombre de un vacío $array=(), la llamada a declarar se asegurará de que obtengamos el resultado correcto
  • Nunca se pasan muchos datos a / dev / null, ya que declarar solo se llama si la variable no está establecida o si es una matriz vacía.

Estas funciones se 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 vea mi answer a la pregunta "¿Cómo verifico si existe una variable en bash?" .

Observación: El uso similar de declare -p, como también se muestra en la answer , es una verdadera coincidencia. De lo contrario, por supuesto, lo habría acreditado!answer

¿Cómo puedo saber si una variable está configurada en Bash?

Por ejemplo, ¿cómo verifico si el usuario asignó el primer parámetro a una función?

function a { # if $1 is set ? }


(Generalmente) El camino correcto

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 no se evalúa en nada si var está establecida, y sustituye la cadena x caso contrario.

Cotizaciones de digresión

Se pueden omitir las cotizaciones (por lo que podemos decir ${var+x} lugar de "${var+x}" ) porque esta sintaxis y uso garantiza que 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 evalúa al mismo valor (verdadero) que [ -z "" ] hace)).

Sin embargo, aunque las citas se pueden omitir de forma segura, y no fue inmediatamente obvio para todos (ni siquiera fue evidente para el primer autor de esta explicación de las citas, que también es un importante programador 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 que usa esta solución y proporciona la URL a esta respuesta, que ahora también incluye la explicación de por qué las citas 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 suele ser 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 "establecer en la cadena vacía" 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 por defecto en un valor no vacío, mientras que la especificación de la cadena vacía debería haga 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.


Quieres salir si no está configurado

Esto funcionó para mí. Quería que mi script saliera con un mensaje de error si no se configuraba 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 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

Solo cheque, no hay salida - Vacío y Desarmado son INVALIDOS

Intente esta opción si solo desea verificar si el valor establecido = 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 cheque, no hay salida - Solo vacío es INVALIDO

Y esta es la respuesta a la pregunta. Use esto si solo quiere verificar 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) que me desafiaron a responder la pregunta con precisión.

Consulte http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02


A continuación, se explica cómo probar si un parámetro no está establecido, está vacío ("Nulo") o se establece 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 mostrados con "sustituto", la expresión se reemplaza con el valor mostrado. En todos los casos mostrados con "asignar", a ese parámetro se le asigna ese valor, que también reemplaza la expresión.


En bash puedes usar -v dentro de la [[ ]] incorporada:

#! /bin/bash -u if [[ ! -v SOMEVAR ]]; then SOMEVAR=''hello'' fi echo $SOMEVAR


En una shell puede usar el operador -z que es verdadero si la longitud de la cadena es cero.

Un sencillo de una sola línea para establecer el valor predeterminado de MY_VAR si no está configurado, de lo contrario, opcionalmente, puede mostrar el mensaje:

[[ -z "$MY_VAR" ]] && MY_VAR="default" [[ -z "$MY_VAR" ]] && MY_VAR="default" || echo "Variable already set."


En una versión moderna de Bash (4.2 o posterior, creo; no lo sé con seguridad), intentarí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


Encontré un código (mucho) mejor para hacer esto si quieres verificar 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, por lo que test -z y test -n no pudieron ayudarte.

Actualización: 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


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.

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


Hay muchas formas de hacer esto con una de las siguientes:

if [ -z "$1" ]

Esto tiene éxito si $ 1 es nulo o no está configurado


Las respuestas anteriores no funcionan cuando Bash option set -u está habilitado. Además, no son dinámicos, por ejemplo, ¿cómo se determina si la variable de prueba con el nombre "ficticio" está definida? 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 puedo probar si una variable está definida en modo "-u"?


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á configurando, pero hay varias cosas que puede hacer con un parámetro si no se establece.

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 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 con $1 en este ejemplo, simplemente salga si no está configurado)


Mi forma preferida es esta:

$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

Entonces, básicamente, si se establece una variable, se convierte en "una negación de la false resultante" (lo que será true = "se establece").

Y, si no se configura, se convertirá en "una negación de la true resultante" (como el resultado vacío se evalúa como true ) (por lo que terminará como false = "NO establecido").


Para aquellos que buscan verificar si no están configurados o están vacíos en un script con set -u :

if [ -z "${var-}" ]; then echo "Must provide var environment variable. Exiting...." exit 1 fi

La verificación regular [ -z "$var" ] fallará con var; unbound variable var; unbound variable si se set -u pero [ -z "${var-}" ] expands a una cadena vacía si var se establece sin error.


Para ver si una variable no está vacía, uso

if [[ $var ]]; then ... # `$var'' expands to a nonempty string

Lo opuesto prueba si una variable está desarmada o vacía:

if [[ ! $var ]]; then ... # `$var'' expands to the empty string (set or not)

Para ver si una variable está configurada (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 comprueba si una variable está desarmada:

if [[ ! ${var+x} ]]; then ... # `var'' is not set at all if [[ ! ${1+x} ]]; then ... # We were called with no arguments


Para verificar la variable de cadena que no sea nula / no cero, es decir, si está establecida, use

if [ -n "$1" ]

Es lo opuesto a -z . Me encuentro usando -n más que -z .


Para verificar si una variable está configurada con un valor no vacío, use [ -n "$x" ] , como ya indicaron 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 puede distinguir los dos si necesita: [ -n "${x+set}" ] ( "${x+set}" expande para set si x está establecido y para la cadena vacía si x está establecida).

Para verificar si se ha pasado un parámetro, pruebe $# , que es el número de parámetros que se han pasado a la función (o al script, cuando no está en una función) (vea la respuesta de Paul ).


Si var puede ser una matriz, la sustitución del parámetro [ -z "${var+x}" ] es incorrecta. Para estar realmente seguro de que en Bash necesita usar una 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 encontré en la que el método de matriz es más preciso es cuando la variable es una matriz no vacía con la posición 0 (por ejemplo, en las pruebas 7 y A continuación). Este desacuerdo se debe a que $var es la abreviatura de ${var[0]} , por lo que [ -z "${var+x}" ] no está verificando toda la matriz.

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} sintaxis de expansión de parámetros de ${var+x} funciona tan bien como la sintaxis de matriz de ${#var[@]} en la mayoría de los casos, como la verificación de parámetros a funciones. La única forma en que se podría romper este caso es si una versión futura de Bash agrega una forma de pasar arreglos a funciones sin convertir los contenidos en argumentos individuales.
  • La sintaxis de la matriz se requiere para las matrices no vacías (asociativas o no) con el elemento 0 .
  • Ninguna de las dos sintaxis explica qué sucede si declare -a var se ha utilizado sin asignar siquiera un valor nulo en algún lugar de la matriz.Bash aún distingue el caso en algún lugar (como se ve en la prueba Banterior), por lo que esta respuesta no es infalible. Afortunadamente, Bash convierte las variables de entorno exportadas en cadenas al ejecutar un programa / script, por lo que cualquier problema con las variables declaradas pero no definidas se incluirá en un solo script, al menos si no está buscando otros scripts.

Si bien la mayoría de las técnicas que se indican 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.

[[ -v foo ]]; echo $? # 1 foo=bar [[ -v foo ]]; echo $? # 0 foo="" [[ -v foo ]]; echo $? # 0


Siempre encuentro que la tabla POSIX en la otra respuesta es lenta a la de los otros , así que aquí está mi opinión:

+----------------------+------------+-----------------------+-----------------------+ | 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 los dos puntos anteriores) tiene los mismos casos establecidos y no configurados , por lo que lo único que difiere es cómo se manejan los casos vacíos .

Con los dos puntos anteriores, los casos vacíos y no configurados son idénticos, por lo que usaría aquellos donde sea posible (es decir, use := , no solo = , porque el caso vacío es inconsistente).

Encabezados:

  • set significa que VARIABLE no está vacío ( VARIABLE="something" )
  • vacío significa VARIABLE está vacío / nulo ( VARIABLE="" )
  • unset significa que 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 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 provista se asigna a la variable para uso futuro.

Siempre uso este, basado en el hecho de que parece fácil ser entendido por cualquiera que vea el código por primera vez:

if [ "$variable" = "" ] then echo "Variable X is empty" fi

Y, si se quiere comprobar si no está vacío;

if [ ! "$variable" = "" ] then echo "Variable X is not empty" fi

Eso es.


Tu puedes hacer:

function a { if [ ! -z "$1" ]; then echo ''$1 is set'' fi }


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 no establecida y una variable establecida en una cadena vacía:

$ set='''' $ [[ -z "$set" ]] && echo "Set" || echo "Unset" Unset $ [[ -z "$unset" ]] && echo "Set" || echo "Unset" Unset

Es mejor verificarlo de acuerdo con 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 verificar la existencia del parámetro $5 ):

[[ $# -ge 5 ]] && echo "Set" || echo "Unset"

Para una variable regular (usando una función auxiliar, para hacerlo de una manera elegante):

function declare_var { declare -p "$1" &> /dev/null return $? } declare_var "var_name" && echo "Set" || echo "Unset"

Notas:

  • $# : te dice 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.

Si desea probar que una variable está vinculada o no vinculada, 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


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}) function IsDeclared_Tricky { local varname="$1" ! [ -z ${!varname+x} ] }

Como primero tuve errores 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 declared function IsDeclared() { declare -p $1 &>/dev/null }

Me parece que es más sencillo, más aburrido 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 declarar var (a menos que seguido por ''=''). Durante bastante tiempo pensé que había declarado las variables de esta manera, solo para descubrir ahora que simplemente expresé mi intención ... Supongo que es una no operación.

IsDeclared_Tricky xyz: 1
IsDeclared_Tricky foo: 1
IsDeclared_Tricky bar: 0
IsDeclared_Tricky baz: 0
IsDeclared xyz
: 1
IsDeclared bar: 1
IsDeclared baz: 0

BONIFICACIÓN: Usecase

Principalmente utilizo esta prueba para dar (y devolver) parámetros a las funciones de una manera "elegante" y segura (casi parecida 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 requeridas declaradas:

¡Hola Mundo!

más:

Error: variable no declarada: outputStr


[[ $foo ]]

O

(( ${#foo} ))

O

let ${#foo}

O

declare -p foo


case "$1" in "") echo "blank";; *) echo "set" esac


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


if [[ ${!xx[@]} ]] ; then echo xx is defined; fi


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