Jeg har sett på noen få skript andre mennesker skrev (spesielt Red Hat), og mange av variablene deres tildeles ved hjelp av følgende notasjon VARIABLE1="${VARIABLE1:-some_val}"
eller noen utvider andre variabler VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"
Hva er vitsen med å bruke denne notasjonen i stedet for bare å erklære verdiene direkte (f.eks. VARIABLE1=some_val
)?
Er det fordeler med denne notasjonen eller mulige feil som kan forhindres?
Har :-
spesifikk betydning i denne sammenhengen ?
Kommentarer
Svar
Denne teknikken gjør det mulig for en variabel å få tildelt en verdi hvis en annen variabel enten er tom eller udefinert. MERK: Denne «andre variabelen» kan være den samme eller en annen variabel.
utdrag
${parameter:-word} If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
MERK: Dette form fungerer også, ${parameter-word}
. Hvis du «vil se en fullstendig liste over alle former for parameterutvidelser som er tilgjengelige i Bash, foreslår jeg sterkt at du tar en titt på dette emnet i Bash Hacker» -wiki med tittelen: « Parameterutvidelse «.
Eksempler
variabelen finnes ikke
$ echo "$VAR1" $ VAR1="${VAR1:-default value}" $ echo "$VAR1" default value
variabel eksisterer
$ VAR1="has value" $ echo "$VAR1" has value $ VAR1="${VAR1:-default value}" $ echo "$VAR1" has value
Det samme kan gjøres ved å evaluere andre variabler, eller kjøre kommandoer innenfor standardverdidelen av notasjonen.
$ VAR2="has another value" $ echo "$VAR2" has another value $ echo "$VAR1" $ $ VAR1="${VAR1:-$VAR2}" $ echo "$VAR1" has another value
Flere eksempler
Du kan også bruke en litt annen notasjon der den bare er VARX=${VARX-<def. value>}
.
$ echo "${VAR1-0}" has another value $ echo "${VAR2-0}" has another value $ echo "${VAR3-0}" 0
I ovenstående $VAR1
& $VAR2
var allerede definert med strengen «har en annen verdi» men $VAR3
var udefinert, så standardverdien ble brukt i stedet, 0
.
Et annet eksempel
$ VARX="${VAR3-0}" $ echo "$VARX" 0
Kontroll og tildeling ved hjelp av :=
notasjon
Til slutt vil jeg nevne den praktiske operatøren, :=
. Dette vil gjøre en sjekk og tildele en verdi hvis variabelen som testes er tom eller udefinert.
Eksempel
Legg merke til at $VAR1
er nå sett. Operatøren :=
gjorde testen og tildelingen i en enkelt operasjon.
$ unset VAR1 $ echo "$VAR1" $ echo "${VAR1:=default}" default $ echo "$VAR1" default
Men hvis verdien er satt tidligere, så er det igjen.
$ VAR1="some value" $ echo "${VAR1:=default}" some value $ echo "$VAR1" some value
Handy Dandy Reference Table
Referanser
Kommentarer
- Merk at ikke alle disse er utvidelser er dokumentert i
bash
.${var:-word}
en i Q er, men ikke${var-word}
over. POSIX Dokumentasjonen har et fint bord skjønt, kan være verdt å kopiere den til th er svar – pubs.opengroup.org/onlinepubs/9699919799/utilities/… - @Graeme, det er dokumentert, du trenger bare å være oppmerksom på Utelatelse av tykktarmen resulterer i en test bare for en parameter som ikke er satt.
- Bruk av
echo "${FOO:=default}"
er flott hvis du faktisk vil haecho
. Men hvis du ikke ‘ t, så prøv:
innebygd …: ${FOO:=default}
Din$FOO
er satt tildefault
som ovenfor (dvs. hvis den ikke allerede er angitt). Men det er ‘ ingen ekko av$FOO
i prosessen. - Ok, fant et svar: stackoverflow.com / q / 24405606/1172302 . Å bruke
${4:-$VAR}
vil fungere. - +1 bare for det detaljerte svaret. Men også for det faktum at du refererer til den utmerkede bash wiki. Og også for det faktum at du gir eksempler og en tabell. Helvete, bare +1 hele veien ned 🙂 Når det gjelder meg hadde jeg nesten syntaksen riktig, men ikke helt – jeg brydde meg bare ikke ‘ til å søke på mannssiden (ikke vanskelig men jeg kunne ikke ‘ ikke huske hvilken overskrift det var under, og jeg ‘ har vært våken siden 4 i morges :() ..
Svar
@slm har allerede tatt med POSIX-dokumenter – som er veldig hjelpsomme – men de utvider egentlig ikke hvordan disse parametrene kan kombineres for å påvirke hverandre. Det er foreløpig ingen omtale her av dette skjemaet:
${var?if unset parent shell dies and this message is output to stderr}
Dette er et utdrag fra et annet svar av meg, og jeg synes det demonstrerer veldig godt hvordan disse fungerer:
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?
Et annet eksempel fra samme :
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
Eksemplet ovenfor utnytter alle 4 former for POSIX-parametererstatning og deres forskjellige :colon null
eller not null
tester. Det er mer informasjon i lenken over, og her er det igjen .
En annen ting som folk ofte ikke vurderer om ${parameter:+expansion}
er hvor veldig nyttig det kan være i et her-dokument. Her er et annet utdrag fra en annet svar :
TOP
Her vil du angi noen standardinnstillinger og forberede deg til å skrive dem ut når du blir ringt …
#!/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
Dette er hvor du definerer andre funksjoner som skal kalles utskriftsfunksjonen din basert på resultatene …
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 }
BUNN
Du har alt oppsett nå, så her er det du skal utføre og trekke resultatene dine.
_less_important_function : "${PLACE:="the cemetery"}" _more_important_function : "${RESULT:="regret it."}" _less_important_function
RESULTATER
Jeg vil se nærmere på hvorfor et øyeblikk, men å kjøre ovenstående gir følgende resultater:
_less_important_function()"s
første løp:Jeg gikk hjem til moren din og så Disney on Ice.
Hvis du gjør kalligrafi vil du lykkes.
th no
_more_important_function():
Jeg dro til kirkegården og så Disney on Ice.
Hvis du gjør avhjelpende matematikk vil du lykkes.
_less_important_function()
igjen:Jeg dro til kirkegården og så Disney on Ice.
Hvis du gjør avhjelpende matematikk, vil du angre på det.
HVORDAN DET FUNGERER:
Nøkkelfunksjonen her er begrepet conditional ${parameter} expansion.
Du kan sette en variabel til en verdi bare hvis den ikke er satt eller null ved hjelp av skjemaet:
${var_name
: =desired_value}
Hvis du i stedet bare vil angi en usett variabel, vil du utelate og nullverdier vil forbli som de er.
PÅ OMFANG:
Du vil kanskje legge merke til at i eksemplet ovenfor $PLACE
og $RESULT
blir endret når de er angitt via parameter expansion
selv om _top_of_script_pr()
allerede er kalt, antagelig innstiller du dem når den kjøres. Grunnen til at dette fungerer er at _top_of_script_pr()
er en ( subshelled )
funksjon – jeg vedlagt det i parens
i stedet for { curly braces }
som brukes til de andre. Fordi den kalles i et subshell, er hver variabel den angir locally scoped
og når den går tilbake til sitt overordnede skall, forsvinner disse verdiene.
Men når _more_important_function()
setter $ACTION
er det globally scoped
så det påvirker _less_important_function()"s
andre evaluering av $ACTION
fordi _less_important_function()
setter $ACTION
bare via ${parameter:=expansion}.
Kommentarer
- Godt å se at standardverdien for stenografi fungerer i Bourne Shell
Svar
Personlig opplevelse.
Jeg bruker dette formatet noen ganger i skriptene mine for å gjøre ad-hoc-overkjøring av verdier, f.eks.hvis jeg har:
$ cat script.sh SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING";
kan jeg løpe:
$ env SOMETHING="something other than the default value" ./script.sh`
uten å måtte endre den opprinnelige standardverdien SOMETHING
.
man bash
; søk etter blokken » Parameterutvidelse » (omtrent 28%). Disse oppgavene er f.eks. standardfunksjoner: » Bruk standardverdien bare hvis ingen er satt ennå. »:-
angir standardverdi,:+
brukes til å endre verdi hvis variabelen er ikke null. F.eks.v=option; cmd ${v:+ with $v}
Kjører » cmd med alternativ «. Men hvis $ v er null, vil den bare kjøre » cmd «.