Usar “ $ {a: -b} ” para la asignación de variables en los scripts

He estado mirando algunos scripts que otras personas escribieron (específicamente Red Hat), y muchas de sus variables se asignan usando la siguiente notación VARIABLE1="${VARIABLE1:-some_val}" o algunas expandir otras variables VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

¿Cuál es el punto de usar esta notación en lugar de simplemente declarar los valores directamente (por ejemplo, VARIABLE1=some_val )?

¿Hay beneficios en esta notación o posibles errores que podrían evitarse?

¿Tiene :- un significado específico en este contexto ?

Comentarios

  • Eche un vistazo a man bash; busque el bloque » Expansión del parámetro » (aproximadamente al 28%). Estas asignaciones son, por ejemplo, funciones predeterminadas: » Use el valor predeterminado solo si aún no se ha establecido ninguno. »
  • Como :- establece el valor predeterminado, el :+ se usa para alterar el valor si la variable es no nulo. P.ej. v=option; cmd ${v:+ with $v} Ejecutará » cmd con la opción «. Pero si $ v es nulo, solo ejecutará » cmd «.

Respuesta

Esta técnica permite asignar un valor a una variable si otra variable está vacía o no está definida. NOTA: Esta «otra variable» puede ser la misma u otra variable.

extracto

${parameter:-word} If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted. 

NOTA: Este El formulario también funciona, ${parameter-word}. Si desea ver una lista completa de todas las formas de expansión de parámetros disponibles en Bash, le sugiero que eche un vistazo a este tema en la wiki de Bash Hacker titulado: « Expansión de parámetros «.

Ejemplos

variable no existe

$ echo "$VAR1" $ VAR1="${VAR1:-default value}" $ echo "$VAR1" default value 

variable existe

$ VAR1="has value" $ echo "$VAR1" has value $ VAR1="${VAR1:-default value}" $ echo "$VAR1" has value 

Se puede hacer lo mismo evaluando otras variables o ejecutando comandos dentro de la parte del valor predeterminado de la notación.

$ VAR2="has another value" $ echo "$VAR2" has another value $ echo "$VAR1" $ $ VAR1="${VAR1:-$VAR2}" $ echo "$VAR1" has another value 

Más ejemplos

También puede usar una notación ligeramente diferente donde «es simplemente VARX=${VARX-<def. value>}.

$ echo "${VAR1-0}" has another value $ echo "${VAR2-0}" has another value $ echo "${VAR3-0}" 0 

En el $VAR1 & ya estaban definidos con la cadena «tiene otro valor» pero $VAR3 no estaba definido, por lo que se usó el valor predeterminado en su lugar, 0.

Otro ejemplo

$ VARX="${VAR3-0}" $ echo "$VARX" 0 

Verificación y asignación usando := notación

Por último, «mencionaré el operador útil, :=. Esto hará una verificación y asignará un valor si la variable bajo prueba está vacía o no está definida.

Ejemplo

Observe que $VAR1 es ahora colocar. El operador := hizo la prueba y la asignación en una sola operación.

$ unset VAR1 $ echo "$VAR1" $ echo "${VAR1:=default}" default $ echo "$VAR1" default 

Sin embargo, si el valor está establecido antes, luego se deja solo.

$ VAR1="some value" $ echo "${VAR1:=default}" some value $ echo "$VAR1" some value 

Handy Dandy Reference Table

        ss de la tabla

Referencias

Comentarios

  • Tenga en cuenta que no todas estas expansiones están documentadas en bash. El ${var:-word} de Q es, pero no el ${var-word} anterior. El POSIX aunque la documentación tiene una buena tabla, podría valer la pena copiarla en th es la respuesta – pubs.opengroup.org/onlinepubs/9699919799/utilities/…
  • @Graeme, está documentado, solo necesita prestar atención a Omitir los dos puntos resulta en una prueba solo para un parámetro que no está establecido.
  • Usando echo "${FOO:=default}" es genial si realmente quieres echo. Pero si no ‘ t, pruebe el : integrado … : ${FOO:=default} Su $FOO está configurado en default como se indicó anteriormente (es decir, si aún no lo ha configurado). Pero ‘ no se repite $FOO en el proceso.
  • Ok, encontré una respuesta: stackoverflow.com / q / 24405606/1172302 . El uso de ${4:-$VAR} funcionará.
  • +1 solo para obtener la respuesta detallada. Pero también por el hecho de que hace referencia a la excelente wiki de bash. Y también por el hecho de que das ejemplos y una tabla. Demonios, solo +1 en todo el camino hacia abajo 🙂 En cuanto a mí, casi tenía la sintaxis correcta, pero no del todo; simplemente no ‘ me importaba lo suficiente como para buscar en la página del manual pero no pude ‘ recordar en qué título estaba y ‘ he estado despierto desde las 4 de esta mañana :() ..

Respuesta

@slm ya ha incluido los documentos POSIX , que son muy útiles, pero en realidad no amplían la forma en que estos parámetros pueden combinarse para afectarse entre sí. Todavía no se menciona aquí esta forma:

${var?if unset parent shell dies and this message is output to stderr} 

Este es un extracto de otra respuesta mía, y creo que demuestra muy bien cómo funcionan:

 sh <<-\CMD _input_fn() { set -- "$@" #redundant echo ${*?WHERES MY DATA?} #echo is not necessary though shift #sure hope we have more than $1 parameter : ${*?WHERES MY DATA?} #: do nothing, gracefully } _input_fn heres some stuff _input_fn one #here # shell dies - third try doesnt run _input_fn you there? # END CMD heres some stuff one sh: line :5 *: WHERES MY DATA? 

Otro ejemplo de igual :

 sh <<-\CMD N= #N is NULL _test=$N #_test is also NULL and v="something you would rather do without" ( #this subshell dies echo "v is ${v+set}: and its value is ${v:+not NULL}" echo "So this ${_test:-"\$_test:="} will equal ${_test:="$v"}" ${_test:+${N:?so you test for it with a little nesting}} echo "sure wish we could do some other things" ) ( #this subshell does some other things unset v #to ensure it is definitely unset echo "But here v is ${v-unset}: ${v:+you certainly wont see this}" echo "So this ${_test:-"\$_test:="} will equal NULL ${_test:="$v"}" ${_test:+${N:?is never substituted}} echo "so now we can do some other things" ) #and even though we set _test and unset v in the subshell echo "_test is still ${_test:-"NULL"} and ${v:+"v is still $v"}" # END CMD v is set: and its value is not NULL So this $_test:= will equal something you would rather do without sh: line 7: N: so you test for it with a little nesting But here v is unset: So this $_test:= will equal NULL so now we can do some other things _test is still NULL and v is still something you would rather do without 

El ejemplo anterior aprovecha las 4 formas de sustitución de parámetros POSIX y sus diversas :colon null o not null pruebas. Hay más información en el enlace anterior y aquí está de nuevo .

Otra cosa que la gente a menudo no considera acerca de ${parameter:+expansion} es lo útil que puede ser en un documento aquí. Aquí hay otro extracto de un respuesta diferente :

ARRIBA

Aquí establecerá algunos valores predeterminados y se preparará para imprimirlos cuando se le llame …

#!/bin/sh _top_of_script_pr() ( IFS="$nl" ; set -f #only split at newlines and don"t expand paths printf %s\\n ${strings} ) 3<<-TEMPLATES ${nl= } ${PLACE:="your mother"s house"} ${EVENT:="the unspeakable."} ${ACTION:="heroin"} ${RESULT:="succeed."} ${strings:=" I went to ${PLACE} and saw ${EVENT} If you do ${ACTION} you will ${RESULT} "} #END TEMPLATES 

MIDDLE

Aquí es donde define otras funciones para llamar a su función de impresión en función de sus resultados …

 EVENT="Disney on Ice." _more_important_function() { #...some logic... [ $((1+one)) -ne 2 ] && ACTION="remedial mathematics" _top_of_script_pr } _less_important_function() { #...more logic... one=2 : "${ACTION:="calligraphy"}" _top_of_script_pr } 

ABAJO

Ya lo tiene todo configurado, así que aquí es donde ejecutará y obtendrá los resultados.

 _less_important_function : "${PLACE:="the cemetery"}" _more_important_function : "${RESULT:="regret it."}" _less_important_function 

RESULTADOS

Voy a explicar por qué en un momento, pero ejecutar lo anterior produce los siguientes resultados:

_less_important_function()"s primera ejecución:

Fui a la casa de tu madre y vi Disney on Ice.

Si haces caligrafía tendrás éxito.

th es _more_important_function():

Fui al cementerio y vi Disney on Ice.

Si haces matemáticas de recuperación tendrás éxito.

_less_important_function() de nuevo:

Fui al cementerio y vi Disney on Ice.

Si haces matemáticas de recuperación, te arrepentirás.

CÓMO FUNCIONA:

La característica clave aquí es el concepto de conditional ${parameter} expansion. Puede establecer una variable en un valor solo si no está configurado o es nulo usando la forma:

${var_name : = desired_value}

Si, en cambio, desea configurar solo una variable no configurada, debe omitir y los valores nulos permanecerían como están.

EN EL ALCANCE:

Puede notar que en el ejemplo anterior $PLACE y $RESULT se modifican cuando se configuran a través de parameter expansion aunque _top_of_script_pr() ya se ha llamado, presumiblemente configurándolos cuando se ejecuta. La razón por la que esto funciona es que _top_of_script_pr() es una función ( subshelled ) – adjunto en parens en lugar de { curly braces } que se usa para los demás. Debido a que se llama en una subcapa, cada variable que establece es locally scoped y cuando regresa a su capa principal esos valores desaparecen.

Pero cuando _more_important_function() establece $ACTION es globally scoped por lo que afecta a _less_important_function()"s segunda evaluación de $ACTION porque _less_important_function() establece $ACTION solo a través de ${parameter:=expansion}.

Comentarios

  • Es bueno ver que el valor predeterminado abreviado funciona en Bourne Shell

Respuesta

Experiencia personal.

A veces utilizo este formato en mis scripts para anular valores ad-hoc, p. ej.si tengo:

$ cat script.sh SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING"; 

Puedo ejecutar:

$ env SOMETHING="something other than the default value" ./script.sh` 

sin tener que cambiar el valor predeterminado original de SOMETHING.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *