bash atribuir valor padrão

135

$ {parameter: = word} Atribuir valores padrão. Se o parâmetro estiver desativado ou nulo, a expansão da palavra será atribuída ao parâmetro. O valor do parâmetro é então substituído. Parâmetros posicionais e especiais não podem ser atribuídos dessa maneira.

Eu pensei que poderia usar esse recurso para escrever em ${LONG_VARIABLE_NAME:=hello}vez de mais LONG_VARIABLE_NAME=${LONG_VARIABLE_NAME:-hello}, mas agora o bash também tenta executar 'hello' e isso fornece um comando não encontrado. Alguma maneira de evitar isso? Ou terei que me ater a este último? Alguém pode dar um exemplo em que o padrão de atribuição é realmente útil?

zedoo
fonte
13
Ao citar texto, é útil incluir um link para a fonte.
Jonathon Reinhart

Respostas:

202

Use dois pontos:

: ${A:=hello}

Os dois pontos são um comando nulo que não faz nada e ignora seus argumentos. Ele é incorporado ao bash para que um novo processo não seja criado.

camh
fonte
93
Não posso deixar de observar que isso : ${A:=hello}é exatamente contanto que A=${A:-hello}. Parece também que o último é um pouco menos esotérico e sua intenção é mais clara. O uso :, que é basicamente um no-op, parece desajeitado em comparação com a maneira como o OP estava fazendo isso antes.
Dan Molding
5
@camh: Concordo. Eu posso ver onde, se você tivesse muitas variáveis ​​para inicializar com os padrões e elas possuírem nomes longos, a :abordagem seria preferível, tanto para digitação quanto para leitura. Sim, parece uma área em que o Bash poderia usar um pouco de melhoria.
Dan Molding
17
@ DanMoulding: o que dizer : ${VERY_LONG_VARIABLE_NAME:=hello}vs VERY_LONG_VARIABLE_NAME=${VERY_LONG_VARIABLE_NAME:-hello}. : . Eu espero que você usar nomes de variáveis descritivos em seu código :)
pihentagy
18
Não apenas mais curto, mas menos propensa a erros: VERY_LONG_VARIABLE_NAME=${VERY_LOGN_VARIABLE_NAME:-hello}. Opa
Chepner 17/08/14
5
Uma vantagem da A=$A:-helloabordagem é que ela é auto-documentada quando executada set -x. Ou seja, a atribuição será impressa como se A=helloo comando nulo apenas imprimisse o valor ( hello).
Lmsurprenant
107

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

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

Se o parâmetro não estiver definido, use o padrão. Após a chamada, o parâmetro ainda não está definido.
Ambas as formas são quase equivalentes. O extra :faz diferença apenas quando o parâmetro foi declarado, mas é 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}

Se o parâmetro não estiver definido, defina o valor do parâmetro como padrão.
Ambas as formas quase equivalentes. O: faz diferença apenas quando o parâmetro foi declarado e é 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}

Se o parâmetro for definido, use alt_value, caso contrário, use cadeia nula. Após a chamada, o valor do parâmetro não foi alterado.
Ambas as formas quase equivalentes. O: faz diferença apenas quando o parâmetro foi declarado e é 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
fonte
20

A expansão do parâmetro de valor padrão geralmente é útil em scripts de construção como o exemplo abaixo. Se o usuário apenas chamar o script como está, o perl não será incorporado. O usuário precisará definir explicitamente WITH_PERLum valor diferente de "não" para integrá-lo.

$ 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

Compilar sem Perl

$ ./defvar.sh
not building with perl

Construa com Perl

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