bash asignar valor predeterminado

135

$ {parámetro: = palabra} Asignar valores predeterminados. Si el parámetro no está establecido o es nulo, la expansión de la palabra se asigna al parámetro. El valor del parámetro se sustituye entonces. Los parámetros posicionales y los parámetros especiales no pueden asignarse de esta manera.

Pensé que podría usar esta función para escribir en ${LONG_VARIABLE_NAME:=hello}lugar de la más larga LONG_VARIABLE_NAME=${LONG_VARIABLE_NAME:-hello}, pero ahora bash también intenta ejecutar 'hola' y eso da un comando no encontrado. ¿Alguna forma de evitar eso? ¿O tendré que apegarme a lo último? ¿Alguien puede dar un ejemplo donde la asignación predeterminada es realmente útil?

zedoo
fuente
13
Al citar texto, es útil incluir un enlace a la fuente.
Jonathon Reinhart

Respuestas:

202

Use dos puntos:

: ${A:=hello}

Los dos puntos son un comando nulo que no hace nada e ignora sus argumentos. Está integrado en bash, por lo que no se crea un nuevo proceso.

camh
fuente
93
No puedo evitar observar que : ${A:=hello}es exactamente el mismo tiempo que A=${A:-hello}. También parece que este último es un poco menos esotérico y su intención es más clara. El uso :, que es básicamente un no-op, parece torpe en comparación con la forma en que el OP lo estaba haciendo antes.
Dan Molding
55
@camh: De acuerdo. Puedo ver dónde, si tuviera muchas variables para inicializar a valores predeterminados y tienen nombres largos, el :enfoque sería preferible, tanto para escribir como para leer. Sí, esto parece un área en la que Bash podría mejorar un poco.
Dan Molding
17
@DanMoulding: ¿qué pasa con : ${VERY_LONG_VARIABLE_NAME:=hello}vs VERY_LONG_VARIABLE_NAME=${VERY_LONG_VARIABLE_NAME:-hello}. : . Espero que utiliza los nombres de variables descriptivas en su código :)
pihentagy
18
No sólo más corto, pero menos propenso a errores: VERY_LONG_VARIABLE_NAME=${VERY_LOGN_VARIABLE_NAME:-hello}. Ups
chepner
55
Una ventaja del A=$A:-helloenfoque es que se documenta automáticamente cuando se ejecuta con set -x. Es decir, la asignación se imprimirá como A=hellomientras que el comando nulo solo imprimiría el valor ( hello).
lmsurprenant
107

Consulte http://www.tldp.org/LDP/abs/html/parameter-substitution.html para ver ejemplos.

${parameter-default}, ${parameter:-default}

Si el parámetro no está configurado, use el predeterminado. Después de la llamada, el parámetro aún no está configurado.
Ambas formas son casi equivalentes. El extra solo :hace la diferencia cuando el parámetro ha sido declarado, pero es nulo.

unset EGGS
echo 1 ${EGGS-spam}   # 1 spam
echo 2 ${EGGS:-spam}  # 2 spam

EGGS=
echo 3 ${EGGS-spam}   # 3
echo 4 ${EGGS:-spam}  # 4 spam

EGGS=cheese
echo 5 ${EGGS-spam}   # 5 cheese
echo 6 ${EGGS:-spam}  # 6 cheese

${parameter=default}, ${parameter:=default}

Si el parámetro no está configurado, configure el valor del parámetro como predeterminado.
Ambas formas casi equivalentes. El: hace la diferencia solo cuando el parámetro ha sido declarado y es nulo

# sets variable without needing to reassign
# colons suppress attempting to run the string
unset EGGS
: ${EGGS=spam}
echo 1 $EGGS     # 1 spam
unset EGGS
: ${EGGS:=spam}
echo 2 $EGGS     # 2 spam

EGGS=
: ${EGGS=spam}
echo 3 $EGGS     # 3        (set, but blank -> leaves alone)
EGGS=
: ${EGGS:=spam}
echo 4 $EGGS     # 4 spam

EGGS=cheese
: ${EGGS:=spam}
echo 5 $EGGS     # 5 cheese
EGGS=cheese
: ${EGGS=spam}
echo 6 $EGGS     # 6 cheese

${parameter+alt_value}, ${parameter:+alt_value}

Si se establece un parámetro, use alt_value, de lo contrario use una cadena nula. Después de la llamada, el valor del parámetro no ha cambiado.
Ambas formas casi equivalentes. El: hace la diferencia solo cuando el parámetro ha sido declarado y es nulo

unset EGGS
echo 1 ${EGGS+spam}  # 1
echo 2 ${EGGS:+spam} # 2

EGGS=
echo 3 ${EGGS+spam}  # 3 spam
echo 4 ${EGGS:+spam} # 4

EGGS=cheese
echo 5 ${EGGS+spam}  # 5 spam
echo 6 ${EGGS:+spam} # 6 spam
Jonathan L
fuente
20

La expansión del parámetro de valor predeterminado a menudo es útil en scripts de compilación como el ejemplo a continuación. Si el usuario simplemente llama al script tal como está, perl no se integrará. El usuario debe establecer explícitamente WITH_PERLun valor distinto de "no" para que se incorpore.

$ cat defvar.sh
#!/bin/bash

WITH_PERL=${WITH_PERL:-no}

if [[ "$WITH_PERL" != no ]]; then
    echo "building with perl"
    # ./configure --enable=perl
else
    echo "not building with perl"
    # ./configure
fi

Construir sin Perl

$ ./defvar.sh
not building with perl

Construye con Perl

$ WITH_PERL=yes ./defvar.sh
building with perl
SiegeX
fuente