Díval jsem se na několik skriptů, které napsali jiní lidé (konkrétně Red Hat), a mnoho jejich proměnných je přiřazeno pomocí následujícího zápisu VARIABLE1="${VARIABLE1:-some_val}" nebo nějakého dalšího proměnné VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"
Jaký má smysl používat tento zápis namísto přímého deklarace hodnot (např. VARIABLE1=some_val )?
Existují výhody tohoto zápisu nebo možné chyby, kterým by se dalo zabránit?
Má :- v tomto kontextu konkrétní význam? ?
Komentáře
Odpověď
Tato technika umožňuje přiřadit proměnné hodnotu, pokud je jiná proměnná prázdná nebo není definována. POZNÁMKA: Tato „jiná proměnná“ může být stejná nebo jiná proměnná.
výňatek
${parameter:-word} If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
POZNÁMKA: Toto formulář také funguje, ${parameter-word}. Pokud byste chtěli vidět úplný seznam všech forem rozšíření parametrů dostupných v Bash, pak vám velmi doporučuji podívat se na toto téma ve wiki Bash Hacker s názvem: „ Rozšíření parametrů „.
Příklady
proměnná neexistuje
$ echo "$VAR1" $ VAR1="${VAR1:-default value}" $ echo "$VAR1" default value
proměnná existuje
$ VAR1="has value" $ echo "$VAR1" has value $ VAR1="${VAR1:-default value}" $ echo "$VAR1" has value
Totéž lze provést vyhodnocením jiných proměnných nebo spuštěním příkazů v části výchozí hodnoty notace.
$ VAR2="has another value" $ echo "$VAR2" has another value $ echo "$VAR1" $ $ VAR1="${VAR1:-$VAR2}" $ echo "$VAR1" has another value
Další příklady
Můžete také použít mírně odlišnou notaci, pokud jde pouze o VARX=${VARX-<def. value>}.
$ echo "${VAR1-0}" has another value $ echo "${VAR2-0}" has another value $ echo "${VAR3-0}" 0
Ve výše uvedeném $VAR1 & $VAR2 již byly definovány pomocí řetězce „has another value“, ale $VAR3 bylo nedefinováno, takže místo toho byla použita výchozí hodnota, 0.
Další příklad
$ VARX="${VAR3-0}" $ echo "$VARX" 0
Kontrola a přiřazování pomocí := notace
Nakonec zmíním praktického operátora, :=. To provede kontrolu a přiřadí hodnotu, pokud je testovaná proměnná prázdná nebo nedefinovaná.
Příklad
Všimněte si, že $VAR1 je nyní soubor. Operátor := provedl test a přiřazení v jediné operaci.
$ unset VAR1 $ echo "$VAR1" $ echo "${VAR1:=default}" default $ echo "$VAR1" default
Je-li však nastavena hodnota předtím, pak už zůstane sám.
$ VAR1="some value" $ echo "${VAR1:=default}" some value $ echo "$VAR1" some value
Handy Dandy Reference Table
Reference
Komentáře
- Všimněte si, že ne všechna rozšíření jsou popsána v
bash.${var:-word}v Q je, ale ne${var-word}výše. POSIX dokumentace má pěknou tabulku, možná by stálo za to ji zkopírovat do th je odpověď – pubs.opengroup.org/onlinepubs/9699919799/utilities/… - @Graeme, je to zdokumentováno, stačí věnovat pozornost Vynechání dvojtečky vede k testu pouze pro parametr, který není nastaven.
- Použití
echo "${FOO:=default}"je skvělý, pokud skutečně chceteecho. Pokud ale ‚ t nevyzkoušíte, zkuste:integrovaný …: ${FOO:=default}Váš$FOOje nastaven nadefault, jak je uvedeno výše (tj. Pokud již není nastaven). Ale ‚ v procesu nedochází k ozvěně$FOO. - Dobře, našel jsem odpověď: stackoverflow.com / q / 24405606/1172302 . Použití
${4:-$VAR}bude fungovat. - +1 pouze pro podrobnou odpověď. Ale také za to, že odkazujete na vynikající bash wiki. A také za to, že uvedete příklady a tabulku. Sakra, jen + 1s úplně dolů 🙂 Co se mě týče, syntaxi jsem téměř měl správně, ale ne tak docela – prostě jsem se ‚ nestaral natolik, abych prohledal manuálovou stránku (není to těžké ale nemohl jsem si ‚ vzpomenout, pod jakým nadpisem to bylo, a ‚ jsem byl vzhůru od 4 ráno :() ..
Odpověď
@slm již zahrnoval POSIX dokumenty – které jsou velmi užitečné – ale ve skutečnosti nerozšíří, jak lze tyto parametry kombinovat tak, aby se vzájemně ovlivňovaly. O tomto formuláři zde zatím není žádná zmínka:
${var?if unset parent shell dies and this message is output to stderr}
Toto je výňatek z další mé odpovědi a myslím, že velmi dobře ukazuje, jak fungují:
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?
Další příklad z stejného :
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
Výše uvedený příklad využívá výhod všech 4 forem substituce parametrů POSIX a jejich různé :colon null nebo not null testy. Ve výše uvedeném odkazu je více informací a je to znovu .
Další věc, o které lidé často neuvažují ${parameter:+expansion}, je, jak velmi užitečná může být v dokumentu zde. Zde je další výňatek z jiná odpověď :
NEJLEPŠÍ
Zde nastavíte některá výchozí nastavení a připravíte se na jejich tisk při volání …
#!/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
STŘEDNÍ
Zde definujete další funkce pro volání vaší tiskové funkce na základě jejich výsledků …
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
Nyní máte vše nastaveno, takže zde můžete provádět a stahovat výsledky.
_less_important_function : "${PLACE:="the cemetery"}" _more_important_function : "${RESULT:="regret it."}" _less_important_function
VÝSLEDKY
Ve chvíli se podívám na důvod, ale spuštění výše uvedeného způsobí následující výsledky:
_less_important_function()"sprvní spuštění:Šel jsem do domu vaší matky a viděl jsem Disney on Ice.
Pokud uděláte kaligrafii , uspějete.
th en
_more_important_function():Šel jsem na hřbitov a viděl Disney on Ice.
Pokud uděláte opravnou matematiku , uspějete.
_less_important_function()znovu:Šel jsem na hřbitov a viděl jsem Disney on Ice.
Pokud se budete věnovat opravné matematice, budete litovat.
JAK TO FUNGUJE:
Klíčovou funkcí je zde koncept conditional ${parameter} expansion. Můžete nastavit proměnnou na hodnota pouze v případě, že je deaktivována nebo nulová pomocí formuláře:
${var_name: =desired_value}
Pokud si přejete nastavit pouze nenastavenou proměnnou, vynechali byste a nulové hodnoty by zůstaly tak, jak jsou.
NA OBLAST PŮSOBNOSTI:
Můžete si všimnout, že ve výše uvedeném příkladu $PLACE a $RESULT se změní, když je nastaveno pomocí parameter expansion i když _top_of_script_pr() již byl volán, pravděpodobně je nastaví, když je spuštěn. Důvod, proč to funguje, je ten, že _top_of_script_pr() je ( subshelled ) funkce – přikládám je v parens spíše než v { curly braces } použitém pro ostatní. Protože se volá v subshellu, každá proměnná, kterou nastaví, je locally scoped a při návratu do nadřazeného shellu tyto hodnoty zmizí.
Ale když _more_important_function() nastaví $ACTION je to globally scoped takže ovlivňuje _less_important_function()"s druhé hodnocení $ACTION protože _less_important_function() nastavuje $ACTION pouze prostřednictvím ${parameter:=expansion}.
Komentáře
- Je dobré vidět, že zkratková výchozí hodnota funguje v Bourne Shell
Odpověď
Osobní zkušenost.
Tento formát někdy používám ve svých skriptech k ad-hoc překročení hodnot, např.pokud mám:
$ cat script.sh SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING";
mohu spustit:
$ env SOMETHING="something other than the default value" ./script.sh`
bez nutnosti změny původní výchozí hodnota SOMETHING.
man bash; vyhledejte blok “ Rozšíření parametrů “ (přibližně 28%). Těmito úkoly jsou např. výchozí funkce: “ Výchozí hodnotu použijte pouze v případě, že ještě nebyla nastavena žádná. “:-nastavuje výchozí hodnotu,:+se používá k změně hodnoty , pokud je proměnná nenulový. Např.v=option; cmd ${v:+ with $v}Spustí “ cmd s možností „. Pokud je však $ v null, spustilo by se to pouze “ cmd „.