Jag har tittat på några skript som andra skrev (speciellt Red Hat), och många av deras variabler tilldelas med hjälp av följande notation VARIABLE1="${VARIABLE1:-some_val}"
eller några utvidgar andra variabler VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"
Vad är poängen med att använda denna notation istället för att bara deklarera värdena direkt (t.ex. VARIABLE1=some_val
)?
Finns det fördelar med denna notation eller möjliga fel som skulle kunna förhindras?
Har :-
en specifik betydelse i detta sammanhang ?
Kommentarer
Svar
Denna teknik gör det möjligt för en variabel att tilldelas ett värde om en annan variabel antingen är tom eller är odefinierad. OBS: Denna ”andra variabel” kan vara samma eller annan variabel.
utdrag
${parameter:-word} If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
OBS: Detta form fungerar också, ${parameter-word}
. Om du ”vill se en fullständig lista över alla former av parameterutvidgningar som finns tillgängliga i Bash, föreslår jag starkt att du tittar på det här ämnet i Bash Hackers wiki med titeln:” Parameterutvidgning ”.
Exempel
variabel finns inte
$ echo "$VAR1" $ VAR1="${VAR1:-default value}" $ echo "$VAR1" default value
variabel existerar
$ VAR1="has value" $ echo "$VAR1" has value $ VAR1="${VAR1:-default value}" $ echo "$VAR1" has value
Samma sak kan göras genom att utvärdera andra variabler, eller genom att köra kommandon inom standardvärdedelen av notationen.
$ VAR2="has another value" $ echo "$VAR2" has another value $ echo "$VAR1" $ $ VAR1="${VAR1:-$VAR2}" $ echo "$VAR1" has another value
Fler exempel
Du kan också använda en något annorlunda notation där det bara är VARX=${VARX-<def. value>}
.
$ echo "${VAR1-0}" has another value $ echo "${VAR2-0}" has another value $ echo "${VAR3-0}" 0
I ovanstående $VAR1
& $VAR2
var redan definierade med strängen ”har ett annat värde” men $VAR3
var odefinierad, så standardvärdet användes istället, 0
.
Ett annat exempel
$ VARX="${VAR3-0}" $ echo "$VARX" 0
Kontroll och tilldelning med :=
notation
Slutligen kommer jag att nämna den praktiska operatören, :=
. Detta gör en kontroll och tilldelar ett värde om variabeln som testas är tom eller odefinierad.
Exempel
Observera att $VAR1
är nu uppsättning. Operatören :=
gjorde testet och tilldelningen i en enda operation.
$ unset VAR1 $ echo "$VAR1" $ echo "${VAR1:=default}" default $ echo "$VAR1" default
Men om värdet är inställt tidigare, då är den ensam.
$ VAR1="some value" $ echo "${VAR1:=default}" some value $ echo "$VAR1" some value
Handy Dandy Reference Table
Referenser
Kommentarer
- Observera att inte alla dessa är utvidgningar dokumenteras i
bash
.${var:-word}
en i Q är, men inte${var-word}
ovan. POSIX Dokumentationen har dock ett trevligt bord, det kan vara värt att kopiera det till det är svar – pubs.opengroup.org/onlinepubs/9699919799/utilities/… - @Graeme, det är dokumenterat, du behöver bara vara uppmärksam på Att utelämna kolon resulterar i ett test endast för en parameter som inte är inställd.
- Användning av
echo "${FOO:=default}"
är jättebra om du faktiskt vill haecho
. Men om du inte ’ t, försök sedan med:
inbyggd …: ${FOO:=default}
Ditt$FOO
är inställt pådefault
som ovan (dvs. om det inte redan är inställt). Men det finns ’ ingen eko av$FOO
i processen. - Ok, hittade ett svar: stackoverflow.com / q / 24405606/1172302 . Att använda
${4:-$VAR}
fungerar. - +1 bara för det detaljerade svaret. Men också för det faktum att du refererar till den utmärkta bash wiki. Och också för det faktum att du ger exempel och en tabell. Helvete, bara +1 hela vägen ner 🙂 När det gäller mig hade jag nästan syntaxen rätt men inte riktigt – jag brydde mig bara inte ’ för att söka på mansidan (inte svårt men jag kunde inte ’ inte komma ihåg vilken rubrik det var under och jag ’ har varit vaken sedan 4 i morse :() ..
Svar
@slm har redan inkluderat POSIX-dokument – som är mycket hjälpsamma – men de utvidgar inte riktigt hur dessa parametrar kan kombineras för att påverka varandra. Det finns ännu inget omnämnande här av denna form:
${var?if unset parent shell dies and this message is output to stderr}
Detta är ett utdrag från ett annat svar till mig, och jag tycker att det visar mycket bra hur dessa fungerar:
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?
Ett annat exempel från samma :
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
Exemplet ovan utnyttjar alla fyra former av POSIX-parameterersättning och deras olika :colon null
eller not null
tester. Det finns mer information i länken ovan, och här är det igen .
En annan sak som människor ofta inte tänker på ${parameter:+expansion}
är hur mycket det kan vara användbart i ett här dokument. Här är ett annat utdrag från en annat svar :
TOP
Här ställer du in några standardinställningar och förbereder dig för att skriva ut dem när du ringer …
#!/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
MIDDEL
Här definierar du andra funktioner som ska användas för din utskriftsfunktion baserat på deras resultat …
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 }
BOTTEN
Du har allt inställt nu, så här kommer du att utföra och dra dina resultat.
_less_important_function : "${PLACE:="the cemetery"}" _more_important_function : "${RESULT:="regret it."}" _less_important_function
RESULTAT
Jag kommer att gå in på varför i ett ögonblick, men att köra ovanstående ger följande resultat:
_less_important_function()"s
första körning:Jag gick till din mors hus och såg Disney on Ice.
Om du gör kalligrafi kommer du att lyckas.
th sv
_more_important_function():
Jag gick till kyrkogården och såg Disney on Ice.
Om du gör avhjälpande matematik kommer du att lyckas.
_less_important_function()
igen:Jag gick till kyrkogården och såg Disney on Ice.
Om du gör avhjälpande matematik kommer du att ångra det.
HUR DET FUNGERAR:
Nyckelfunktionen här är begreppet conditional ${parameter} expansion.
Du kan ställa in en variabel till en värde bara om det är avstängt eller noll med hjälp av formuläret:
${var_name
: =desired_value}
Om du istället bara vill ställa in en icke inställd variabel, skulle du utelämna och nullvärden skulle förbli som de är.
PÅ OMFATTNING:
Du kanske märker att i exemplet ovan $PLACE
och $RESULT
ändras när de ställs in via parameter expansion
även om _top_of_script_pr()
redan har anropats, antagligen ställer du in dem när den körs. Anledningen till att detta fungerar är att _top_of_script_pr()
är en ( subshelled )
funktion – jag bifogade det i parens
snarare än { curly braces }
som används för de andra. Eftersom den kallas i en subshell är varje variabel som den anger locally scoped
och när den återgår till sitt överordnade skal försvinner dessa värden.
Men när _more_important_function()
ställer in $ACTION
är det globally scoped
så det påverkar _less_important_function()"s
andra utvärderingen av $ACTION
eftersom _less_important_function()
ställer $ACTION
endast via ${parameter:=expansion}.
Kommentarer
- Bra att se att det förkortade standardvärdet fungerar i Bourne Shell
Svar
Personlig upplevelse.
Jag använder det här formatet ibland i mina skript för att göra ad hoc-överdrift av värden, t.ex.om jag har:
$ cat script.sh SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING";
kan jag köra:
$ env SOMETHING="something other than the default value" ./script.sh`
utan att behöva ändra det ursprungliga standardvärdet SOMETHING
.
man bash
; sök efter blocket ” Parameterutvidgning ” (cirka 28%). Dessa uppdrag är t.ex. standardfunktioner: ” Använd endast standardvärdet om inget har ställts in ännu. ”:-
anger standardvärde,:+
används för att ändra värde om variabeln är inte null. T.ex.v=option; cmd ${v:+ with $v}
Kör ” cmd med alternativ ”. Men om $ v är null, skulle det bara köras ” cmd ”.