¿Qué significa: $ {param: = value}?

34

Leí lo siguiente en la Guía del usuario de Z-Shell :

Un sinónimo de 'verdadero' es ':'; a menudo se usa en esta forma para dar argumentos que tienen efectos secundarios pero que no deberían usarse, algo así como

: ${param:=value}

que es un idioma común en todos los derivados de shell Bourne. En la expansión del parámetro, $paramse le da el valor del valor si antes estaba vacío y, de lo contrario, se deja solo. Dado que esa era la única razón para la expansión del parámetro, solía :ignorar el argumento. En realidad, el shell construye alegremente la línea de comando (los dos puntos, seguidos del valor que $paramsea, independientemente de si la asignación se realizó o no) y luego ejecuta el comando; da la casualidad de que ':' no tiene en cuenta los argumentos que se le dieron.

Pero no lo entiendo. Entiendo que :significa true, pero hay dos puntos en la expresión. Como una pregunta menor, ¿por qué este lenguaje se usa tanto en todos los derivados de shell Bourne? ¿Para qué sirve?

Nota: Estoy interesado en lo que hace este modismo tanto en bash como en zsh .

Gracias

Amelio Vazquez-Reina
fuente
¿Estás pidiendo zsho bash?
enzotib
@enzotib, estoy interesado en ambos. Aclaré eso.
Amelio Vazquez-Reina

Respuestas:

31

Rompamos esto en pedazos.

Este código ejecuta el comando :con algunos argumentos. El comando :no hace nada e ignora sus argumentos. Por lo tanto, toda la línea de comando no hace nada, excepto los efectos secundarios que suceden en los argumentos.

La sintaxis ${parameter_name:=value}existe en todos los depósitos de estilo Bourne no antiguos, incluidos ash, bash, ksh y zsh. Establece el parámetro por defecto si es necesario. Es equivalente a

if [ -z "$parameter_name" ]; then parameter_name=value; fi
 ${parameter_name}

En otras palabras, si parameter_nameno se establece o se establece en un valor vacío, configúrelo en el valor indicado; y luego ejecute el comando, utilizando el nuevo valor del parámetro. Hay una variante, ${parameter_name=value}que deja el parámetro vacío si estaba vacío, solo usando el valor indicado si el parámetro no estaba configurado.

Encontrará esta sintaxis documentada en "expansión de parámetros" en la especificación POSIX y los manuales dash, bash, ksh y zsh.

Hay variaciones en esta sintaxis, en particular, ${parameter_name:-value}que le permiten usar un valor predeterminado para esta expansión solamente, sin asignar el parámetro.

En resumen, : ${parameter_name:=value}es una forma concisa de escribir

if [ -z "$parameter_name" ]; then parameter_name=value; fi
Gilles 'SO- deja de ser malvado'
fuente
11

:no significa verdadero, probablemente estás pensando while :, pero incluso en esa expresión no significa "verdadero", simplemente sucede evaluarlo (de hecho, es simplemente un comando nulo o noop).

Este parámetro de expansión ( ${x:=y}) significa "asignar y a x si x está desarmado o vacío, y expandir a y ".

$ echo "${foo:=bar}"
bar
$ foo=baz
$ echo "${foo:=bar}"
baz
$ foo=
$ echo "${foo:=bar}"
bar
$ echo "${foo}"
bar

El wiki de Bash Hackers tiene un buen artículo sobre la expansión de parámetros aquí .

La razón que :se usa es para que, aunque se evalúen otras partes del comando, no se actúe sobre ellas (como :es un comando nulo). Por lo tanto, debe ${x:=y}realizar su función sin afectar nada más, por ejemplo, si no tenía el :al principio, intentaría ejecutar un comando llamado y .

Aquí está bashla página de ayuda sobre ::

:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.
Chris Down
fuente
3

El primero :es un comando, se llama "noop" o "no operation". Como se dijo en la página de manual, a menudo se usa para evaluar los argumentos.

El segundo :es un calificador en la expansión variable, técnicamente lo es :=. Que como se dijo, esto establece el valor si no tiene un valor.

En términos idiomáticos, si necesita un valor predeterminado de una variable de entorno, puede usar esta sintaxis. Por ejemplo, al ejecutar un programa cron(8), el entorno no está configurado y los archivos de puntos del shell no se ejecutan. Por lo tanto, es posible que deba establecer algunos valores predeterminados.

: ${JAVA_HOME:=/usr/local/jdk-1.6.0_28}

Luego puede 'configurarlo y olvidarlo' (hasta que cambie el jvm predeterminado).

Arcege
fuente