Utilizarea “ $ {a: -b} ” pentru atribuirea variabilelor în scripturi

M-am uitat la câteva scripturi scrise de alte persoane (în special Red Hat) și multe dintre variabilele lor sunt atribuite folosind următoarea notație VARIABLE1="${VARIABLE1:-some_val}" sau unele extind altele variabile VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

Ce rost are utilizarea acestei notații în loc să declarați direct valorile (de exemplu, VARIABLE1=some_val )?

Există beneficii pentru această notație sau posibile erori care ar fi prevenite?

Are :- o semnificație specifică în acest context? ?

Comentarii

  • Aruncați o privire la man bash; căutați blocul ” Extindere parametru ” (la aproximativ 28%). Aceste sarcini sunt de ex. funcții implicite: ” Utilizați valoarea implicită numai dacă încă nu a fost setată niciuna. ”
  • Ca :- setează valoarea implicită, :+ este folosit pentru a modifica valoarea dacă variabila este nu nul. De exemplu. v=option; cmd ${v:+ with $v} Va rula ” cmd cu opțiunea „. Dar dacă $ v este nul, va rula numai ” cmd „.

Răspuns

Această tehnică permite unei variabile să i se atribuie o valoare dacă o altă variabilă este fie goală, fie nedefinită. NOTĂ: Această „altă variabilă” poate fi aceeași sau o altă variabilă.

extras

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

NOTĂ: Aceasta formularul funcționează și, ${parameter-word}. Dacă doriți să vedeți o listă completă a tuturor formelor de extindere a parametrilor disponibile în cadrul Bash, vă recomand să aruncați o privire asupra acestui subiect în wiki-ul Bash Hacker intitulat: „ Extinderea parametrilor „.

Exemple

variabila nu există

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

variabilă există

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

Același lucru se poate face evaluând alte variabile sau executând comenzi în porțiunea de valoare implicită a notației.

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

Mai multe exemple

Puteți utiliza, de asemenea, o notație ușor diferită, acolo unde este doar VARX=${VARX-<def. value>}.

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

În $VAR1 & $VAR2 au fost deja definite cu șirul „are altă valoare”, dar $VAR3 a fost nedefinit, așa că valoarea implicită a fost utilizată în schimb, 0.

Un alt exemplu

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

Verificarea și atribuirea utilizând notarea :=

În cele din urmă, voi menționa operatorul la îndemână, :=. Aceasta va face o verificare și va atribui o valoare dacă variabila testată este goală sau nedefinită.

Exemplu

Observați că $VAR1 este acum a stabilit. Operatorul := a efectuat testul și atribuirea într-o singură operație.

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

Cu toate acestea, dacă valoarea este setată anterior, atunci „rămâne singur.

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

Tabel de referință Handy Dandy

        ss din tabel

Referințe

Comentarii

  • Rețineți că nu toate acestea sunt extinderi sunt documentate în bash. ${var:-word} din Q este, dar nu ${var-word} de mai sus. POSIX documentația are un tabel frumos, totuși, ar merita să o copiați în th is answer – pubs.opengroup.org/onlinepubs/9699919799/utilities/…
  • @Graeme, este documentat, trebuie doar să fiți atenți la Omiterea rezultatelor de două puncte într-un test numai pentru un parametru care nu este setat.
  • Utilizarea echo "${FOO:=default}" este minunat dacă doriți de fapt echo. Dar dacă nu ‘ t, încercați : încorporat … : ${FOO:=default} $FOO este setat la default ca mai sus (adică, dacă nu este deja setat). Dar ‘ nu are ecou în $FOO în proces.
  • Ok, am găsit un răspuns: stackoverflow.com / q / 24405606/1172302 . Folosirea ${4:-$VAR} va funcționa.
  • +1 doar pentru răspunsul detaliat. Dar și pentru faptul că faceți referire la excelentul bash wiki. Și, de asemenea, pentru faptul că dați exemple și un tabel. La naiba, doar +1 până la capăt 🙂 În ceea ce mă privește, aproape că aveam sintaxa corectă, dar nu chiar – nu mi-a păstrat suficient ‘ suficient pentru a căuta în pagina manuală (nu greu dar nu am putut ‘ să-mi amintesc sub ce rubrică se afla și am ‘ de când am fost treaz de la 4 dimineața asta :() ..

Răspuns

@slm a inclus deja documente POSIX – care sunt foarte utile – dar nu se extind cu adevărat asupra modului în care acești parametri pot fi combinați pentru a se afecta reciproc. Nu există încă nicio mențiune aici despre acest formular:

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

Acesta este un extras din un alt răspuns al meu și cred că demonstrează foarte bine cum funcționează acestea:

 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 alt exemplu din același :

 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 

Exemplul de mai sus profită de toate cele 4 forme de substituire a parametrilor POSIX și diversele lor teste :colon null sau not null . Există mai multe informații în linkul de mai sus și aici este din nou .

Un alt lucru pe care oamenii nu îl consideră adesea despre ${parameter:+expansion} este cât de util poate fi într-un document aici. Iată un alt extras dintr-un răspuns diferit :

TOP

Aici veți seta câteva valori implicite și vă veți pregăti să le tipăriți când sunteți …

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

MEDIU

Aici definiți alte funcții pentru a apela funcția de imprimare pe baza rezultatelor lor …

 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

Ați configurat totul acum, așa că aici veți executa și extrage rezultatele.

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

REZULTATE

Voi analiza de ce într-un moment, dar executarea celor de mai sus produce următoarele rezultate:

_less_important_function()"s prima rundă:

M-am dus la casa mamei tale și am văzut Disney on Ice.

Dacă faci caligrafie vei reuși.

th ro _more_important_function():

Am fost la cimitirul și a văzut Disney pe gheață.

Dacă faci matematică corectivă vei reuși.

_less_important_function() din nou:

Am fost la cimitir și am văzut Disney pe gheață.

Dacă faceți matematică de remediere, veți regreta.

CUM FUNCȚIONEAZĂ:

Caracteristica cheie aici este conceptul de conditional ${parameter} expansion. Puteți seta o variabilă la valoare numai dacă este nesetată sau nulă utilizând formularul:

${var_name : = desired_value}

Dacă în schimb doriți să setați doar o variabilă nesetată, ați omite și valorile nule ar rămâne așa cum sunt.

PE DOMENIU:

S-ar putea să observați că în exemplul de mai sus $PLACE și $RESULT se modifică atunci când sunt setate prin parameter expansion chiar dacă _top_of_script_pr() a fost deja apelat, setându-i probabil când se execută. Motivul pentru care funcționează este că _top_of_script_pr() este o funcție ( subshelled ) – am inclus în parens mai degrabă decât în { curly braces } folosit pentru celelalte. Deoarece este apelat într-un sub-shell, fiecare variabilă pe care o setează este locally scoped și pe măsură ce revine la shell-ul său părinte, aceste valori dispar.

Dar când _more_important_function() setează $ACTION este globally scoped deci afectează _less_important_function()"s a doua evaluare a $ACTION deoarece _less_important_function() setează $ACTION numai prin ${parameter:=expansion}.

Comentarii

  • Este bine să văd că valoarea implicită a prescurtării funcționează în Bourne Shell

Răspuns

Experiență personală.

Folosesc acest format uneori în scripturile mele pentru a face o depășire ad-hoc a valorilor, de ex.dacă am:

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

Pot rula:

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

fără a fi nevoie să mă schimb valoarea implicită inițială a SOMETHING.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *