Usando “ $ {a: -b} ” para atribuição de variável em scripts

Tenho observado alguns scripts que outras pessoas escreveram (especificamente Red Hat), e muitas de suas variáveis são atribuídas usando a seguinte notação VARIABLE1="${VARIABLE1:-some_val}" ou alguma outra expansão variáveis VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

Qual é o sentido de usar essa notação em vez de apenas declarar os valores diretamente (por exemplo, VARIABLE1=some_val )?

Existem benefícios nesta notação ou possíveis erros que seriam evitados?

O :- tem um significado específico neste contexto ?

Comentários

  • Dê uma olhada em man bash; procure o bloco ” Expansão de parâmetro ” (em cerca de 28%). Essas atribuições são, por exemplo, funções padrão: ” Use o valor padrão apenas se nenhum tiver sido definido ainda. ”
  • Como :- define o valor padrão, o :+ é usado para alterar o valor se a variável for não nulo. Por exemplo. v=option; cmd ${v:+ with $v} Será executado ” cmd com a opção “. Mas se $ v for nulo, ele executará apenas ” cmd “.

Resposta

Esta técnica permite que uma variável seja atribuída um valor se outra variável estiver vazia ou indefinida. OBSERVAÇÃO: Essa “outra variável” pode ser a mesma ou outra variável.

trecho

${parameter:-word} If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted. 

NOTA: Isso formulário também funciona, ${parameter-word}. Se você gostaria de ver uma lista completa de todas as formas de expansão de parâmetro disponíveis no Bash, então sugiro que dê uma olhada neste tópico no wiki do Bash Hacker intitulado: “ Expansão de parâmetros “.

Exemplos

variável não” existe

$ echo "$VAR1" $ VAR1="${VAR1:-default value}" $ echo "$VAR1" default value 

variável existe

$ VAR1="has value" $ echo "$VAR1" has value $ VAR1="${VAR1:-default value}" $ echo "$VAR1" has value 

A mesma coisa pode ser feita avaliando outras variáveis ou executando comandos dentro da parte do valor padrão da notação.

$ VAR2="has another value" $ echo "$VAR2" has another value $ echo "$VAR1" $ $ VAR1="${VAR1:-$VAR2}" $ echo "$VAR1" has another value 

Mais exemplos

Você também pode usar uma notação ligeiramente diferente onde “é apenas VARX=${VARX-<def. value>}.

$ echo "${VAR1-0}" has another value $ echo "${VAR2-0}" has another value $ echo "${VAR3-0}" 0 

No $VAR1 & já foram definidos com a string “tem outro valor”, mas $VAR3 foi indefinido, então o valor padrão foi usado, 0.

Outro exemplo

$ VARX="${VAR3-0}" $ echo "$VARX" 0 

Verificação e atribuição usando := notação

Por último, mencionarei o operador útil, :=. Isso fará uma verificação e atribuirá um valor se a variável em teste estiver vazia ou indefinida.

Exemplo

Observe que $VAR1 é agora definir. O operador := fez o teste e a atribuição em uma única operação.

$ unset VAR1 $ echo "$VAR1" $ echo "${VAR1:=default}" default $ echo "$VAR1" default 

No entanto, se o valor for definido antes, então é deixado sozinho.

$ VAR1="some value" $ echo "${VAR1:=default}" some value $ echo "$VAR1" some value 

Tabela de referência dândi útil

        ss da tabela

Referências

Comentários

  • Observe que nem todas essas expansões estão documentadas em bash. O ${var:-word} no Q é, mas não o ${var-word} acima. O POSIX documentação tem uma boa tabela, porém, pode valer a pena copiá-la para o é a resposta – pubs.opengroup.org/onlinepubs/9699919799/utilities/…
  • @ Graeme, está documentado, você só precisa prestar atenção a Omitindo os resultados de dois pontos em um teste apenas para um parâmetro que não está definido.
  • Usando echo "${FOO:=default}" é ótimo se você realmente deseja o echo. Mas se você não ‘ t, tente o : integrado … : ${FOO:=default} Seu $FOO está definido para default como acima (ou seja, se ainda não estiver definido). Mas não ‘ s nenhum eco de $FOO no processo.
  • Ok, encontrei uma resposta: stackoverflow.com / q / 24405606/1172302 . Usar o ${4:-$VAR} funcionará.
  • +1 apenas para a resposta detalhada. Mas também pelo fato de você fazer referência ao excelente bash wiki. E também pelo fato de você dar exemplos e uma tabela. Inferno, apenas + 1s até o final 🙂 Quanto a mim, quase acertei a sintaxe, mas não muito – eu simplesmente não ‘ me importei o suficiente para pesquisar a página de manual (não é difícil mas eu não conseguia ‘ não lembrar em que título estava e ‘ estive acordado desde as 4 da manhã :() ..

Resposta

@slm já incluiu os documentos POSIX – que são muito úteis – mas não expandem realmente como esses parâmetros podem ser combinados para afetar um ao outro. Ainda não há qualquer menção aqui a este formulário:

${var?if unset parent shell dies and this message is output to stderr} 

Este é um trecho de outra resposta minha , e acho que demonstra muito bem como funcionam:

 sh <<-\CMD _input_fn() { set -- "$@" #redundant echo ${*?WHERES MY DATA?} #echo is not necessary though shift #sure hope we have more than $1 parameter : ${*?WHERES MY DATA?} #: do nothing, gracefully } _input_fn heres some stuff _input_fn one #here # shell dies - third try doesnt run _input_fn you there? # END CMD heres some stuff one sh: line :5 *: WHERES MY DATA? 

Outro exemplo de mesmo :

 sh <<-\CMD N= #N is NULL _test=$N #_test is also NULL and v="something you would rather do without" ( #this subshell dies echo "v is ${v+set}: and its value is ${v:+not NULL}" echo "So this ${_test:-"\$_test:="} will equal ${_test:="$v"}" ${_test:+${N:?so you test for it with a little nesting}} echo "sure wish we could do some other things" ) ( #this subshell does some other things unset v #to ensure it is definitely unset echo "But here v is ${v-unset}: ${v:+you certainly wont see this}" echo "So this ${_test:-"\$_test:="} will equal NULL ${_test:="$v"}" ${_test:+${N:?is never substituted}} echo "so now we can do some other things" ) #and even though we set _test and unset v in the subshell echo "_test is still ${_test:-"NULL"} and ${v:+"v is still $v"}" # END CMD v is set: and its value is not NULL So this $_test:= will equal something you would rather do without sh: line 7: N: so you test for it with a little nesting But here v is unset: So this $_test:= will equal NULL so now we can do some other things _test is still NULL and v is still something you would rather do without 

O exemplo acima tira vantagem de todas as 4 formas de substituição de parâmetro POSIX e seus diversos testes :colon null ou not null . Há mais informações no link acima e aqui está novamente .

Outra coisa que as pessoas geralmente não consideram sobre ${parameter:+expansion} é o quão útil pode ser em um documento aqui. Aqui está outro trecho de um resposta diferente :

TOP

Aqui, você definirá alguns padrões e se preparará para imprimi-los quando chamado …

#!/bin/sh _top_of_script_pr() ( IFS="$nl" ; set -f #only split at newlines and don"t expand paths printf %s\\n ${strings} ) 3<<-TEMPLATES ${nl= } ${PLACE:="your mother"s house"} ${EVENT:="the unspeakable."} ${ACTION:="heroin"} ${RESULT:="succeed."} ${strings:=" I went to ${PLACE} and saw ${EVENT} If you do ${ACTION} you will ${RESULT} "} #END TEMPLATES 

MEIO

Aqui é onde você define outras funções para chamar sua função de impressão com base em seus resultados …

 EVENT="Disney on Ice." _more_important_function() { #...some logic... [ $((1+one)) -ne 2 ] && ACTION="remedial mathematics" _top_of_script_pr } _less_important_function() { #...more logic... one=2 : "${ACTION:="calligraphy"}" _top_of_script_pr } 

BOTTOM

Você já configurou tudo agora, então aqui “é onde você” executará e obterá seus resultados.

 _less_important_function : "${PLACE:="the cemetery"}" _more_important_function : "${RESULT:="regret it."}" _less_important_function 

RESULTADOS

Explicarei o porquê em um momento, mas a execução do procedimento acima produz os seguintes resultados:

_less_important_function()"s primeira execução:

Fui à casa da sua mãe e vi Disney on Ice.

Se você fizer caligrafia , terá sucesso.

th en _more_important_function():

Fui ao cemitério e viu Disney no gelo.

Se você fizer matemática corretiva , terá sucesso.

_less_important_function() novamente:

Fui ao cemitério e vi Disney no gelo.

Se você fizer matemática corretiva, você se arrependerá.

COMO FUNCIONA:

O principal recurso aqui é o conceito de conditional ${parameter} expansion. Você pode definir uma variável para um valor apenas se não estiver definido ou nulo usando o formulário:

${var_name : = desired_value}

Se, em vez disso, você quiser definir apenas uma variável não definida, omita o e os valores nulos permaneceriam como estão.

NO ESCOPO:

Você pode notar que no exemplo acima $PLACE e $RESULT são alterados quando configurados via parameter expansion embora _top_of_script_pr() já tenha sido chamado, presumivelmente configurando-os quando for executado. A razão de isso funcionar é que _top_of_script_pr() é uma função ( subshelled ) – incluí em parens em vez de { curly braces } usado para os outros. Por ser chamado em um subshell, cada variável que define é locally scoped e, conforme retorna ao shell pai, esses valores desaparecem.

Mas quando _more_important_function() define $ACTION , é globally scoped para que afete _less_important_function()"s segunda avaliação de $ACTION porque _less_important_function() define $ACTION somente por meio de ${parameter:=expansion}.

Comentários

  • É bom ver que o valor padrão abreviado funciona no Bourne Shell

Resposta

Experiência pessoal.

Eu uso esse formato às vezes em meus scripts para fazer a substituição ad hoc de valores, por exemplo,se eu tenho:

$ cat script.sh SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING"; 

Posso executar:

$ env SOMETHING="something other than the default value" ./script.sh` 

sem ter que mudar o valor padrão original de SOMETHING.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *