O que significa: $ {param: = value} significa?

24

Eu li o seguinte em Guia do usuário do Z-Shell :

A synonym for ‘true’ is ‘:’; it’s often used in this form to give arguments which have side effects but which shouldn’t be used — something like

: ${param:=value}

which is a common idiom in all Bourne shell derivatives. In the parameter expansion, $param is given the value value if it was empty before, and left alone otherwise. Since that was the only reason for the parameter expansion, you use : to ignore the argument. Actually, the shell blithely builds the command line — the colon, followed by whatever the value of $param is, whether or not the assignment happened — then executes the command; it just so happens that ‘:’ takes no notice of the arguments it was given.

mas eu não entendo isso. Eu recebo que : significa true , mas existem dois dois pontos na expressão. Como uma questão menor, por que essa expressão é tão usada em todos os derivados de shell Bourne? Para que serve isso?

Nota: Estou interessado no que esse idioma faz em bash e em zsh .

Obrigado

    
por Amelio Vazquez-Reina 26.11.2011 / 23:06

3 respostas

25

Vamos dividir isso em pedaços.

Este código executa o comando : com alguns argumentos. O comando : não faz nada e ignora seus argumentos. Portanto, toda a linha de comando não faz nada, exceto quaisquer efeitos colaterais que aconteçam nos argumentos.

A sintaxe ${parameter_name:=value} existe em todos os shells no estilo Bourne não antigos, incluindo ash, bash, ksh e zsh. Define o parâmetro como padrão, se necessário. É equivalente a

if [ -z "$parameter_name" ]; then parameter_name=value; fi
… ${parameter_name}

Em outras palavras, se parameter_name não estiver definido ou estiver definido como um valor vazio, defina-o como o valor indicado; e, em seguida, execute o comando, usando o novo valor de parâmetro. Existe uma variante, ${parameter_name=value} , que deixa o parâmetro vazio se estiver vazio, usando apenas o valor indicado se o parâmetro não foi definido.

Você encontrará essa sintaxe documentada em "expansão de parâmetro" na especificação POSIX e os manuais dash, bash, ksh e zsh.

Existem variações nesta sintaxe, em particular ${parameter_name:-value} , que permitem usar apenas um valor padrão para essa expansão, sem atribuir ao parâmetro.

Em resumo, : ${parameter_name:=value} é uma maneira concisa de escrever

if [ -z "$parameter_name" ]; then parameter_name=value; fi
    
por 27.11.2011 / 00:59
9

: não significa verdadeiro - você provavelmente está pensando em while : , mas mesmo nessa expressão não significa "verdadeiro", simplesmente acontece de avaliá-lo (na verdade, é simplesmente um comando nulo ou noop).

Esta expansão de parâmetro ( ${x:=y} ) significa "atribuir y a x se x não estiver definida ou vazia, e expandir para y ".

$ echo "${foo:=bar}"
bar
$ foo=baz
$ echo "${foo:=bar}"
baz
$ foo=
$ echo "${foo:=bar}"
bar
$ echo "${foo}"
bar

O wiki do Bash Hackers tem um bom artigo sobre a expansão de parâmetros aqui .

O motivo pelo qual : é usado é para que, enquanto outras partes do comando são avaliadas, elas não sejam postas em prática (pois : é um comando nulo). Assim, você tem ${x:=y} executando sua função sem afetar qualquer outra coisa, por exemplo, se você não tivesse o : no começo, ele tentaria executar um comando chamado y . / p>

Esta é a página de ajuda de bash em : :

:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.
    
por 26.11.2011 / 23:48
3

O primeiro : é um comando, é chamado de "noop" ou "no operation". Como dito na manpage, é freqüentemente usado para avaliar os argumentos.

O segundo : é um qualificador na expansão de variável - tecnicamente é := . Como dito, isso define o valor se não tiver um valor.

Idiomática, se você precisar de um valor padrão de uma variável de ambiente, poderá usar essa sintaxe. Por exemplo, ao executar um programa através de cron(8) , o ambiente não está definido e os arquivos de ponto do shell não são executados. Então você pode precisar definir alguns padrões.

: ${JAVA_HOME:=/usr/local/jdk-1.6.0_28}

Então você pode 'definir e esquecer' (até que o jvm padrão mude).

    
por 26.11.2011 / 23:48

Tags