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

34

Li o seguinte no Guia do Usuário do Z-Shell :

Um sinônimo para 'true' é ':'; é frequentemente usado neste formulário para fornecer argumentos que têm efeitos colaterais, mas que não devem ser usados ​​- algo como

: ${param:=value}

que é um idioma comum em todos os derivados de shell Bourne. Na expansão do parâmetro, $paramé dado o valor value se ele estava vazio antes e deixado sozinho caso contrário. Como esse foi o único motivo da expansão do parâmetro, você usa :para ignorar o argumento. Na verdade, o shell constrói alegremente a linha de comando - os dois pontos, seguidos de qualquer valor que $paramseja, independentemente de a atribuição ter acontecido ou não - e depois executa o comando; acontece que ':' não toma conhecimento dos argumentos que foram apresentados.

mas eu não entendo isso. Recebo que :meios true, mas há dois dois pontos na expressão. Como uma questão menor, por que esse idioma é usado tanto em todos os derivados de shell Bourne? Que finalidade serve?

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

obrigado

Amelio Vazquez-Reina
fonte
Você está pedindo zshou bash?
enzotib 26/11/11
@enzotib, estou interessado em ambos. Eu esclareci isso.
Amelio Vazquez-Reina

Respostas:

31

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 os efeitos colaterais que ocorrem nos argumentos.

A sintaxe ${parameter_name:=value}existe em todos os shells no estilo Bourne não antigos, incluindo ash, bash, ksh e zsh. Ele 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_namenão estiver definido ou definido como um valor vazio, defina-o como o valor indicado; e, em seguida, execute o comando, usando o novo valor do 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 estiver definido.

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

Existem variações nessa sintaxe, em particular ${parameter_name:-value}que permitem usar um valor padrão apenas para esta 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
Gilles 'SO- parar de ser mau'
fonte
11

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

Este parâmetro expansion ( ${x:=y}) significa "atribua y a x se x estiver desabilitado ou vazio e expanda a 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 expansão de parâmetros aqui .

O motivo :usado é que, enquanto outras partes do comando são avaliadas, elas não são acionadas (como :é um comando nulo). Assim, você ${x:=y}desempenha sua função sem afetar mais nada, por exemplo, se você não a tiver :no início, ele tentará executar um comando chamado y .

Aqui está basha página de ajuda de ::

:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.
Chris Down
fonte
3

O primeiro :é um comando, chamado "noop" ou "no operation". Como dito na página de manual, é frequentemente usado para avaliar os argumentos.

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

No idioma, se você precisar de um valor padrão de uma variável de ambiente, poderá usar esta sintaxe. Por exemplo, ao executar um programa cron(8), o ambiente não está definido e os arquivos de ponto do shell não são executados. Portanto, pode ser necessário definir alguns padrões.

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

Então você pode 'configurá-lo e esquecê-lo' (até que a jvm padrão seja alterada).

Arcege
fonte