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
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
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 faptecho
. Dar dacă nu ‘ t, încercați:
încorporat …: ${FOO:=default}
$FOO
este setat ladefault
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
.
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. ”:-
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 „.