Cosa significa: $ {param: = value}?


34

Ho letto quanto segue nella Guida per l'utente di Z-Shell :

Un sinonimo di "vero" è ":"; è spesso usato in questa forma per dare argomenti che hanno effetti collaterali ma che non dovrebbero essere usati - qualcosa del genere

: ${param:=value}

che è un linguaggio comune in tutti i derivati ​​della shell Bourne. Nell'espansione dei parametri, $paramviene assegnato il valore se era vuoto prima e lasciato solo in caso contrario. Poiché quello era l'unico motivo per l'espansione del parametro, si usa :per ignorare l'argomento. In realtà, la shell costruisce allegramente la riga di comando - i due punti, seguiti da qualunque sia il valore di $param, indipendentemente dal fatto che l'assegnazione sia avvenuta o meno - quindi esegue il comando; succede solo che ':' non si accorge degli argomenti che gli è stato dato.

ma non lo capisco. Capisco che :significa true, ma ci sono due due punti nell'espressione. Come domanda minore, perché questo idioma è usato così tanto in tutti i derivati ​​della shell Bourne? A quale scopo serve?

Nota: sono interessato a ciò che fa questo idioma sia in bash che in zsh .

Grazie


Stai chiedendo zsho bash?
enzotib,

@enzotib, mi interessano entrambi. L'ho chiarito.
Amelio Vazquez-Reina,

Risposte:


31

Dividiamolo in pezzi.

Questo codice esegue il comando :con alcuni argomenti. Il comando :non fa nulla e ignora i suoi argomenti. Pertanto l'intera riga di comando non fa nulla, tranne gli effetti collaterali che si verificano negli argomenti.

La sintassi ${parameter_name:=value}esiste in tutte le conchiglie non antiche in stile Bourne, tra cui ash, bash, ksh e zsh. Se necessario, imposta il parametro su un valore predefinito. È equivalente a

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

In altre parole, se parameter_namenon è impostato o è impostato su un valore vuoto, impostarlo sul valore indicato; e quindi eseguire il comando, utilizzando il nuovo valore del parametro. Esiste una variante, ${parameter_name=value}che lascia vuoto il parametro se era vuoto, utilizzando solo il valore indicato se il parametro non era impostato.

Questa sintassi è documentata nella sezione "Espansione dei parametri" nelle specifiche POSIX e nei manuali dash, bash, ksh e zsh.

Esistono variazioni su questa sintassi, in particolare ${parameter_name:-value}che consentono di utilizzare un valore predefinito solo per questa espansione, senza assegnare al parametro.

In sintesi, : ${parameter_name:=value}è un modo conciso di scrivere

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

11

:non significa vero - probabilmente stai pensando while :, ma anche in quell'espressione non significa "vero", semplicemente accade valutarlo (in realtà, è semplicemente un comando nullo o noop).

Questo parametro di espansione ( ${x:=y}) significa "assegna y a x se x non è impostato o vuoto ed espandi a y ".

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

La wiki di Bash Hackers ha un buon articolo sull'espansione dei parametri qui .

Il motivo :utilizzato è che, mentre vengono valutate altre parti del comando, non vengono applicate (come :è un comando null). Pertanto, hai ${x:=y}svolto la sua funzione senza influenzare nient'altro, ad esempio, se non avessi :all'inizio, proverebbe a eseguire un comando chiamato y .

Ecco bashla pagina di aiuto su ::

:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.

3

Il primo :è un comando, si chiama "noop" o "nessuna operazione". Come detto nella manpage, viene spesso utilizzato per valutare gli argomenti.

Il secondo :è un qualificatore dell'espansione variabile - tecnicamente lo è :=. Come detto, questo imposta il valore se non ha un valore.

Per quanto riguarda il linguaggio, se hai bisogno di un valore predefinito di una variabile d'ambiente, puoi usare questa sintassi. Ad esempio, quando si esegue un programma cron(8), l'ambiente non è impostato e i file di punti della shell non vengono eseguiti. Quindi potrebbe essere necessario impostare alcune impostazioni predefinite.

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

Quindi puoi "impostarlo e dimenticarlo" (fino a quando non viene modificata la jvm predefinita).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.