Utilizzo di “ $ {a: -b} ” per lassegnazione di variabili negli script

Ho esaminato alcuni script scritti da altre persone (in particolare Red Hat) e molte delle loro variabili sono assegnate utilizzando la seguente notazione VARIABLE1="${VARIABLE1:-some_val}" o altre espansioni variabili VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

Qual è il punto di utilizzare questa notazione invece di dichiarare direttamente i valori (ad esempio, VARIABLE1=some_val )?

Ci sono vantaggi in questa notazione o possibili errori che potrebbero essere evitati?

:- ha un significato specifico in questo contesto ?

Commenti

  • Dai unocchiata a man bash; cerca il blocco ” Parameter Expansion ” (al 28% circa). Questi incarichi sono ad es. funzioni predefinite: ” Utilizza il valore predefinito solo se non ne è stato ancora impostato nessuno. ”
  • As :- imposta il valore predefinito, :+ viene utilizzato per alterare il valore se la variabile è non nullo. Per esempio. v=option; cmd ${v:+ with $v} Verrà eseguito ” cmd con lopzione “. Ma se $ v è nullo, verrà eseguito solo ” cmd “.

Risposta

Questa tecnica consente di assegnare un valore a una variabile se unaltra variabile è vuota o non è definita. NOTA: questa “altra variabile” può essere la stessa o unaltra variabile.

estratto

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

NOTA: funziona anche il modulo, ${parameter-word}. Se “desideri vedere un elenco completo di tutte le forme di espansione dei parametri disponibili in Bash, ti consiglio caldamente di dare unocchiata a questo argomento nel wiki di Bash Hacker” dal titolo: “ Espansione parametro “.

Esempi

la variabile non” esiste

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

variabile esiste

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

La stessa cosa può essere eseguita valutando altre variabili o eseguendo comandi allinterno della parte del valore predefinito della notazione.

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

Altri esempi

Puoi anche utilizzare una notazione leggermente diversa in cui “è solo VARX=${VARX-<def. value>}.

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

In $VAR1 & $VAR2 erano già definiti con la stringa “has another value” ma $VAR3 non era definito, quindi è stato utilizzato il valore predefinito 0.

Un altro esempio

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

Controllo e assegnazione utilizzando la notazione :=

Infine menzionerò loperatore pratico, :=. Questo eseguirà un controllo e assegnerà un valore se la variabile sottoposta a test è vuota o non definita.

Esempio

Nota che $VAR1 è ora impostato. Loperatore := ha eseguito il test e lassegnazione in ununica operazione.

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

Tuttavia, se il valore è impostato prima, poi è lasciato solo.

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

Tabella di riferimento Handy Dandy

        ss of table

Riferimenti

Commenti

  • Nota che non tutte queste sono espansioni sono documentate in bash. Quello ${var:-word} nella Q è, ma non il ${var-word} sopra. Il POSIX la documentazione ha una bella tabella, potrebbe valere la pena copiarla in th è answer – pubs.opengroup.org/onlinepubs/9699919799/utilities/…
  • @Graeme, è documentato, devi solo prestare attenzione al Omettendo i due punti risulta in un test solo per un parametro non impostato.
  • Utilizzando echo "${FOO:=default}" è ottimo se vuoi effettivamente echo. Ma se non ‘ t, prova il : integrato … : ${FOO:=default} Il tuo $FOO è impostato su default come sopra (cioè, se non è già impostato). Ma ‘ non cè eco di $FOO nel processo.
  • Ok, ho trovato una risposta: stackoverflow.com / q / 24405606/1172302 . Lutilizzo del ${4:-$VAR} funzionerà.
  • +1 solo per la risposta dettagliata. Ma anche per il fatto che fai riferimento alleccellente wiki di bash. E anche per il fatto che fornisci esempi e una tabella. Diamine, solo +1 fino in fondo 🙂 Per quanto mi riguarda avevo quasi la sintassi giusta ma non del tutto – semplicemente ‘ non mi interessava abbastanza da cercare nella pagina man (non difficile ma non riuscivo ‘ a ricordare sotto quale intestazione si trovava e ‘ sono sveglio dalle 4 di questa mattina :() ..

Risposta

@slm ha già incluso i documenti POSIX – che sono molto utili – ma in realtà non spiegano come questi parametri possono essere combinati per influenzarsi a vicenda. Non cè ancora alcuna menzione qui di questa forma:

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

Questo è un estratto da unaltra mia risposta , e penso che dimostri molto bene come funzionano:

 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? 

Un altro esempio da stesso :

 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 

Lesempio precedente sfrutta tutte e 4 le forme di sostituzione dei parametri POSIX e i loro vari test :colon null o not null . Sono disponibili ulteriori informazioni nel link sopra e eccole di nuovo .

Unaltra cosa che le persone spesso non considerano di ${parameter:+expansion} è quanto possa essere molto utile in un here-document. Ecco un altro estratto da un risposta diversa :

TOP

Qui imposterai alcune impostazioni predefinite e ti preparerai a stamparle quando chiamate …

#!/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 

MIDDLE

Qui è dove definisci altre funzioni da chiamare sulla tua funzione di stampa in base ai loro risultati …

 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

Ora hai tutto configurato, quindi ecco dove eseguirai e recupererai i risultati.

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

RISULTATI

Spiegherò il motivo tra un momento, ma lesecuzione di quanto sopra produce i seguenti risultati:

_less_important_function()"s prima esecuzione:

Sono andato a casa di tua madre e ho visto Disney on Ice.

Se fai calligrafia avrai successo.

th it _more_important_function():

Sono andato al cimitero e ho visto Disney on Ice.

Se fai matematica correttiva avrai successo.

_less_important_function() di nuovo:

Sono andato al cimitero e ho visto Disney on Ice.

Se ti occupi di matematica correttiva, te ne pentirai.

COME FUNZIONA:

La caratteristica chiave qui è il concetto di conditional ${parameter} expansion. Puoi impostare una variabile su un valore solo se non è impostato o è nullo utilizzando il formato:

${var_name : = desired_value}

Se invece desideri impostare solo una variabile non impostata, ometti il e i valori null rimarrebbero come sono.

IN AMBITO:

Potresti notare che nellesempio precedente $PLACE e $RESULT vengono modificati se impostati tramite parameter expansion anche se _top_of_script_pr() è già stato chiamato, presumibilmente impostandoli quando viene eseguito. Il motivo per cui funziona è che _top_of_script_pr() è una funzione ( subshelled ) – ho incluso in parens anziché in { curly braces } utilizzato per gli altri. Poiché è chiamata in una subshell, ogni variabile che imposta è locally scoped e quando ritorna alla sua shell genitrice quei valori scompaiono.

Ma quando _more_important_function() imposta $ACTION è globally scoped quindi influisce sulla _less_important_function()"s seconda valutazione di $ACTION perché _less_important_function() imposta $ACTION solo tramite ${parameter:=expansion}.

Commenti

  • È bello vedere che il valore predefinito della scorciatoia funziona in Bourne Shell

Risposta

Esperienza personale.

A volte utilizzo questo formato nei miei script per sovrascrivere i valori ad hoc, ad es.se ho:

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

posso eseguire:

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

senza dover modificare il valore predefinito originale di SOMETHING.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *