Atribuindo valores padrão a variáveis ​​do shell com um único comando no bash

682

Eu tenho um monte de testes de variáveis ​​em um script de shell bash (3.00), onde se a variável não estiver definida, ela atribui um padrão, por exemplo:

if [ -z "${VARIABLE}" ]; then 
    FOO='default'
else 
    FOO=${VARIABLE}
fi

Eu me lembro que há alguma sintaxe para fazer isso em uma linha, algo semelhante a um operador ternário, por exemplo:

FOO=${ ${VARIABLE} : 'default' }

(embora eu saiba que não vai funcionar ...)

Eu sou louco, ou existe algo assim?

Edward Q. Bridges
fonte
1
A seção Expansão dos parâmetros do shell da referência do shell bash é um bom ponto de partida: tiswww.case.edu/php/chet/bash/bashref.html#Shell-Expansions .
Kemin Zhou
1
Documentação do Gnu.org para Shell Parameter Expansion (dica: há muitas outras coisas legais que você pode fazer!)
JDB ainda se lembra de Monica

Respostas:

1225

Muito perto do que você postou, na verdade:

FOO=${VARIABLE:-default}  # If variable not set or null, use default.

Ou, o que irá atribuir defaultao VARIABLEbem:

FOO=${VARIABLE:=default}  # If variable not set or null, set it to default.
Andrew McGregor
fonte
64
Se eu quisesse encontrar isso na documentação, o que seria um google? Pesquisar no Google caracteres especiais como $ {: -} não é muito fácil.
Joshua Olson
20
Em resposta a solarmist: "bash variável atribuição padrão" deixe-me a esta página e página de manual em busca de festa com 'ass variável' me levou para a seção logo após ~ cinco 'próximo'
Mooshu
57
Nota que é não específicas de festa e vai trabalhar com o todo shell-família. É seguro para scripts genéricos.
Jocelyn delalande
16
@solarmist A palavra-chave é "expansão dos parâmetros do bash", se você quiser saber mais sobre ele e seus companheiros.
precisa saber é o seguinte
20
Aqui está uma explicação mais aprofundada sobre o tema unix.stackexchange.com/a/122848/2407
jottr
288

Para argumentos de linha de comando:

VARIABLE=${1:-DEFAULTVALUE}    

que atribui ao VARIABLEvalor do 1º argumento passado ao script ou ao valor de DEFAULTVALUEse nenhum argumento foi passado.

miku
fonte
243

Se a variável for a mesma, então

: "${VARIABLE:=DEFAULT_VALUE}"

atribui DEFAULT_VALUE a VARIABLE, se não definido. As aspas duplas impedem a ocorrência de globbing e divisão de palavras.

Consulte também a Seção 3.5.3, Expansão de parâmetros do shell , no manual do Bash.

Hans Ginzel
fonte
27
Esse truque complicado não era óbvio para mim, usando o: sem efeito embutido para comer a expansão do $ {..} MAS deixando VARIABLE definido. Até agora eu estava fazendo isso: VARIABLE = "$ {VARIABLE: -DEFAULT_VALUE}" e me sentindo um idiota por usar VARIABLE duas vezes.
dino
Acontece que isso nem sempre funciona para variáveis ​​de bash-buildil. É muito, muito estranho. Atualmente, aqueles que me são conhecidos sãoHISTTIMEFORMAT
Otheus 13/04/16
como eu definiria vários valores padrão? Eu tentei ": $ {VARIÁVEL: = DEFAULT_VALUE}: $ {variavel2: = DEFAULT_VALUE2}", mas isso não parece funcionar ...
Hans
8
@ Hans: O cólon é o comando (que não faz nada) e, portanto, é necessário apenas uma vez. Exemplo: ${FOO:=DEFAULT1} ${BAR:=DEFAULT2}
Patrik
34

Mesmo você pode usar como valor padrão o valor de outra variável

tendo um arquivo defvalue.sh

#!/bin/bash
variable1=$1
variable2=${2:-$variable1}

echo $variable1
echo $variable2

executar ./defvalue.sh first-value second-valuesaída

first-value
second-value

e execute a ./defvalue.sh first-valuesaída

first-value
first-value
Montells
fonte
27

veja aqui em 3.5.3 (expansão dos parâmetros do shell)

então no seu caso

${VARIABLE:-default}
ghostdog74
fonte
25

Para responder à sua pergunta e em todas as substituições de variáveis

echo "$\{var}"
echo "Substitute the value of var."


echo "$\{var:-word}"
echo "If var is null or unset, word is substituted for var. The value of var does not change."


echo "$\{var:=word}"
echo "If var is null or unset, var is set to the value of word."


echo "$\{var:?message}"
echo "If var is null or unset, message is printed to standard error. This checks that variables are set correctly."


echo "$\{var:+word}"
echo "If var is set, word is substituted for var. The value of var does not change."
Guru
fonte
17

FWIW, você pode fornecer uma mensagem de erro da seguinte forma:

USERNAME=${1:?"Specify a username"}

Isso exibe uma mensagem como esta e sai com o código 1:

./myscript.sh
./myscript.sh: line 2: 1: Specify a username

Um exemplo mais completo de tudo:

#!/bin/bash
ACTION=${1:?"Specify 'action' as argv[1]"}
DIRNAME=${2:-$PWD}
OUTPUT_DIR=${3:-${HOMEDIR:-"/tmp"}}

echo "$ACTION"
echo "$DIRNAME"
echo "$OUTPUT_DIR"

Resultado:

$ ./script.sh foo
foo
/path/to/pwd
/tmp

$ export HOMEDIR=/home/myuser
$ ./script.sh foo
foo
/path/to/pwd
/home/myuser
  • $ACTION pega o valor do primeiro argumento e sai se estiver vazio
  • $DIRNAME é o segundo argumento e o padrão é o diretório atual
  • $OUTPUT_DIRé o terceiro argumento, ou $HOMEDIR(se definido), caso contrário /tmp,. Isso funciona no OS X, mas não tenho certeza de que seja portátil.
Curtis Mattoon
fonte
16

Depois, há a maneira de expressar sua construção "se" de maneira mais concisa:

FOO='default'
[ -n "${VARIABLE}" ] && FOO=${VARIABLE}
Rob Wells
fonte
9

Aqui está um exemplo

#!/bin/bash

default='default_value'
value=${1:-$default}

echo "value: [$value]"

salve isso como script.sh e torne-o executável. executá-lo sem parâmetros

./script.sh
> value: [default_value]

executá-lo com param

./script.sh my_value
> value: [my_value]
Assaf Shomer
fonte