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?


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.

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.


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.


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

27

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

então no seu caso

${VARIABLE:-default}

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."

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.

16

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

FOO='default'
[ -n "${VARIABLE}" ] && FOO=${VARIABLE}

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]
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.