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áš$FOO
je 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()"s
první 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 „.