Jeg har kigget på et par scripts, som andre skrev (specifikt Red Hat), og mange af deres variabler tildeles ved hjælp af følgende notation VARIABLE1="${VARIABLE1:-some_val}"
eller nogle udvider andre variabler VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"
Hvad er meningen med at bruge denne notation i stedet for bare at erklære værdierne direkte (f.eks. VARIABLE1=some_val
)?
Er der fordele ved denne notation eller mulige fejl, der kunne forhindres?
Har :-
en specifik betydning i denne sammenhæng ?
Kommentarer
Svar
Denne teknik tillader, at en variabel tildeles en værdi, hvis en anden variabel enten er tom eller udefineret. BEMÆRK: Denne “anden variabel” kan være den samme eller en anden variabel.
uddrag
${parameter:-word} If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
BEMÆRK: Dette form fungerer også, ${parameter-word}
. Hvis du gerne vil se en komplet liste over alle former for parameterudvidelse, der er tilgængelig inden for Bash, foreslår jeg stærkt, at du ser på dette emne i Bash Hackers wiki med titlen: “ Parameterudvidelse “.
Eksempler
variabel findes ikke
$ echo "$VAR1" $ VAR1="${VAR1:-default value}" $ echo "$VAR1" default value
variabel findes
$ VAR1="has value" $ echo "$VAR1" has value $ VAR1="${VAR1:-default value}" $ echo "$VAR1" has value
Den samme ting kan gøres ved at evaluere andre variabler eller køre kommandoer inden for standardværdien af notationen.
$ VAR2="has another value" $ echo "$VAR2" has another value $ echo "$VAR1" $ $ VAR1="${VAR1:-$VAR2}" $ echo "$VAR1" has another value
Flere eksempler
Du kan også bruge en lidt anden notation, hvor 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 defineret med strengen “har en anden værdi” men $VAR3
var udefineret, så standardværdien blev brugt i stedet for, 0
.
Et andet eksempel
$ VARX="${VAR3-0}" $ echo "$VARX" 0
Kontrol og tildeling ved hjælp af :=
notation
Endelig vil jeg nævne den praktiske operatør, :=
. Dette foretager en kontrol og tildeler en værdi, hvis variablen under test er tom eller udefineret.
Eksempel
Bemærk, at $VAR1
er nu sæt. Operatøren :=
udførte testen og tildelingen i en enkelt operation.
$ unset VAR1 $ echo "$VAR1" $ echo "${VAR1:=default}" default $ echo "$VAR1" default
Men hvis værdien er indstillet forud, så er den alene.
$ VAR1="some value" $ echo "${VAR1:=default}" some value $ echo "$VAR1" some value
Reference Dandy Reference Table
Referencer
Kommentarer
- Bemærk, at ikke alle disse er udvidelser er dokumenteret i
bash
.${var:-word}
en i Q er, men ikke${var-word}
ovenfor. POSIX Dokumentationen har dog et godt bord, men det kan være værd at kopiere det til th er svar – pubs.opengroup.org/onlinepubs/9699919799/utilities/… - @Graeme, det er dokumenteret, du skal bare være opmærksom på Hvis kolon udelades, resulterer der kun i en test for en parameter, der ikke er indstillet.
- Brug af
echo "${FOO:=default}"
er fantastisk, hvis du rent faktisk vil haveecho
. Men hvis du ikke ‘ t, så prøv:
indbygget …: ${FOO:=default}
Din$FOO
er indstillet tildefault
som ovenfor (dvs. hvis den ikke allerede er indstillet). Men der er ‘ ingen ekko af$FOO
i processen. - Ok, fandt et svar: stackoverflow.com / q / 24405606/1172302 . Brug af
${4:-$VAR}
fungerer. - +1 kun for det detaljerede svar. Men også for det faktum, at du refererer til den fremragende bash wiki. Og også for det faktum, at du giver eksempler og en tabel. Helvede, bare + 1 hele vejen ned 🙂 Hvad mig angår, havde jeg næsten syntaksen ret, men ikke helt – jeg var bare ikke ‘ t pleje nok til at søge på mandsiden (ikke hårdt men jeg kunne ikke ‘ ikke huske, hvilken overskrift det var under, og jeg ‘ har været vågen siden 4 i morges :() ..
Svar
@slm har allerede inkluderet POSIX-dokumenter – som er meget nyttige – men de udvider ikke rigtig, hvordan disse parametre kan kombineres for at påvirke hinanden. Her nævnes denne form endnu ikke:
${var?if unset parent shell dies and this message is output to stderr}
Dette er et uddrag fra et andet svar af mig, og jeg synes, det viser 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 andet 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
Ovenstående eksempel udnytter alle 4 former for POSIX-parameterudskiftning og deres forskellige :colon null
eller not null
tests. Der er flere oplysninger i linket ovenfor, og her er det igen .
En anden ting, som folk ofte ikke overvejer ${parameter:+expansion}
er, hvor meget nyttigt det kan være i et her-dokument. Her er et andet uddrag fra en andet svar :
TOP
Her angiver du nogle standardindstillinger og forbereder dig til at udskrive dem, når de kaldes …
#!/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
Det er her, du definerer andre funktioner, der skal kaldes din udskrivningsfunktion ud fra deres resultater …
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 }
BUNDT
Du har fået det hele opsat nu, så her er det, hvor du “udfører og trækker dine resultater.
_less_important_function : "${PLACE:="the cemetery"}" _more_important_function : "${RESULT:="regret it."}" _less_important_function
RESULTATER
Jeg vil se nærmere på hvorfor i et øjeblik, men at køre ovenstående giver følgende resultater:
_less_important_function()"s
første kørsel:Jeg gik til din mors hus og så Disney on Ice.
Hvis du laver kalligrafi vil du få succes.
th da
_more_important_function():
Jeg gik til kirkegården og så Disney on Ice.
Hvis du laver afhjælpende matematik vil du få succes.
_less_important_function()
igen:Jeg gik til kirkegården og så Disney on Ice.
Hvis du foretager afhjælpende matematik, vil du fortryde det.
SÅDAN FUNGERER DET:
Nøglefunktionen her er begrebet conditional ${parameter} expansion.
Du kan indstille en variabel til en værdi kun, hvis den ikke er indstillet eller nul ved hjælp af formularen:
${var_name
: =desired_value}
Hvis du i stedet kun ønsker at indstille en ikke-indstillet variabel, vil du udelade og nullværdier forbliver som de er.
PÅ OMFANG:
Du bemærker muligvis, at i ovenstående eksempel $PLACE
og $RESULT
ændres, når de indstilles via parameter expansion
selvom _top_of_script_pr()
allerede er blevet kaldt, hvilket sandsynligvis indstilles, når den køres. Årsagen til, at dette fungerer, er, at _top_of_script_pr()
er en ( subshelled )
funktion – jeg vedlagte det i parens
snarere end { curly braces }
bruges til de andre. Fordi den kaldes i en subshell, er hver variabel, den indstiller, locally scoped
og når den vender tilbage til sin overordnede shell, forsvinder disse værdier.
Men når _more_important_function()
indstiller $ACTION
er det globally scoped
så det påvirker _less_important_function()"s
anden evaluering af $ACTION
fordi _less_important_function()
kun $ACTION
kun via ${parameter:=expansion}.
Kommentarer
- Godt at se, at standardværdien for stenografi fungerer i Bourne Shell
Svar
Personlig oplevelse.
Jeg bruger dette format nogle gange i mine scripts til at udføre ad-hoc overstyring af værdier, f.eks.hvis jeg har:
$ cat script.sh SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING";
kan jeg køre:
$ env SOMETHING="something other than the default value" ./script.sh`
uden at skulle ændre den oprindelige standardværdi på SOMETHING
.
man bash
; søg efter blokken ” Parameterudvidelse ” (ca. 28%). Disse opgaver er f.eks. standardfunktioner: ” Brug kun standardværdien, hvis ingen endnu er indstillet. ”:-
indstiller standardværdi,:+
bruges til at ændre værdi hvis variabel er ikke null. For eksempel.v=option; cmd ${v:+ with $v}
Kører ” cmd med option “. Men hvis $ v er nul, kører den kun ” cmd “.