“ $ {a: -b} ” gebruiken voor variabeletoekenning in scripts

Ik heb gekeken naar een paar scripts die andere mensen hebben geschreven (met name Red Hat), en veel van hun variabelen zijn toegewezen met de volgende notatie VARIABLE1="${VARIABLE1:-some_val}" of sommige breiden andere uit variabelen VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

Wat heeft het voor zin deze notatie te gebruiken in plaats van alleen de waarden rechtstreeks te declareren (bijv. VARIABLE1=some_val )?

Zijn er voordelen aan deze notatie of mogelijke fouten die zouden worden voorkomen?

Heeft de :- een specifieke betekenis in deze context ?

Reacties

  • Kijk eens naar man bash; zoek naar het blok ” Parameteruitbreiding ” (ongeveer 28%). Deze opdrachten zijn b.v. standaardfuncties: ” Gebruik de standaardwaarde alleen als er nog geen is ingesteld. ”
  • Als :- stelt de standaardwaarde in, de :+ wordt gebruikt om waarde te wijzigen als variabele is niet nul. Bijv. v=option; cmd ${v:+ with $v} Zal ” cmd uitvoeren met optie “. Maar als $ v nul is, zou het alleen ” cmd ” draaien.

Answer

Met deze techniek kan aan een variabele een waarde worden toegekend als een andere variabele leeg of niet gedefinieerd is. OPMERKING: Deze “andere variabele” kan dezelfde of een andere variabele zijn.

uittreksel

${parameter:-word} If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted. 

OPMERKING: Dit formulier werkt ook, ${parameter-word}. Als je “graag een volledige lijst wilt zien van alle vormen van parameteruitbreiding die beschikbaar zijn in Bash, dan raad ik je ten zeerste aan om dit onderwerp te bekijken in de wiki van Bash Hacker met de titel:” Parameteruitbreiding “.

Voorbeelden

variabele bestaat niet

$ echo "$VAR1" $ VAR1="${VAR1:-default value}" $ echo "$VAR1" default value 

variabele bestaat

$ VAR1="has value" $ echo "$VAR1" has value $ VAR1="${VAR1:-default value}" $ echo "$VAR1" has value 

Hetzelfde kan worden gedaan door andere variabelen te evalueren, of door opdrachten uit te voeren binnen het standaardwaarde-gedeelte van de notatie.

$ VAR2="has another value" $ echo "$VAR2" has another value $ echo "$VAR1" $ $ VAR1="${VAR1:-$VAR2}" $ echo "$VAR1" has another value 

Meer voorbeelden

Je kunt ook een iets andere notatie gebruiken waar het “gewoon VARX=${VARX-<def. value>} is.

$ echo "${VAR1-0}" has another value $ echo "${VAR2-0}" has another value $ echo "${VAR3-0}" 0 

In het bovenstaande $VAR1 & $VAR2 waren al gedefinieerd met de string “heeft een andere waarde” maar $VAR3 was niet gedefinieerd, dus werd de standaardwaarde gebruikt, 0.

Nog een voorbeeld

$ VARX="${VAR3-0}" $ echo "$VARX" 0 

Controleren en toewijzen met := notatie

Ten slotte noem ik de handige operator :=. Dit zal een controle uitvoeren en een waarde toekennen als de te testen variabele leeg of niet gedefinieerd is.

Voorbeeld

Merk op dat $VAR1 nu is set. De operator := heeft de test en de toewijzing in een enkele handeling uitgevoerd.

$ unset VAR1 $ echo "$VAR1" $ echo "${VAR1:=default}" default $ echo "$VAR1" default 

Als de waarde is ingesteld voorafgaand, dan wordt het met rust gelaten.

$ VAR1="some value" $ echo "${VAR1:=default}" some value $ echo "$VAR1" some value 

Handige Dandy Reference Table

        ss of table

Referenties

Reacties

  • Merk op dat niet al deze uitbreidingen zijn gedocumenteerd in bash. De ${var:-word} in de Q is, maar niet de ${var-word} hierboven. De POSIX documentatie heeft echter een mooie tabel, misschien is het de moeite waard om het naar th te kopiëren is antwoord – pubs.opengroup.org/onlinepubs/9699919799/utilities/…
  • @Graeme, het is gedocumenteerd, je hoeft alleen maar te letten op de Het weglaten van de dubbele punt resulteert in een test alleen voor een parameter die niet is ingesteld.
  • Gebruik van echo "${FOO:=default}" is geweldig als je de echo echt wilt. Maar als u ‘ t niet gebruikt, probeer dan de : ingebouwde … : ${FOO:=default} Uw $FOO is ingesteld op default zoals hierboven (dwz, indien nog niet ingesteld). Maar er ‘ is geen echo van $FOO in het proces.
  • Ok, vond een antwoord: stackoverflow.com / q / 24405606/1172302 . Het gebruik van de ${4:-$VAR} zal werken.
  • +1 alleen voor het gedetailleerde antwoord. Maar ook vanwege het feit dat je verwijst naar de uitstekende bash-wiki. En ook voor het feit dat je voorbeelden en een tabel geeft. Hell, gewoon + 1s helemaal naar beneden 🙂 Wat mij betreft, ik had bijna de syntaxis goed, maar niet helemaal – ik ‘ kon het gewoon niet genoeg schelen om de man-pagina te doorzoeken (niet moeilijk maar ik kon ‘ me niet herinneren onder welke kop het stond en ik ‘ ben wakker sinds 4 vanmorgen :() ..

Antwoord

@slm heeft al de POSIX-documenten – die erg nuttig zijn – maar ze “breiden niet echt uit hoe deze parameters gecombineerd kunnen worden om elkaar te beïnvloeden. Er wordt hier nog geen melding gemaakt van dit formulier:

${var?if unset parent shell dies and this message is output to stderr} 

Dit is een fragment uit een ander antwoord van mij, en ik denk dat het heel goed laat zien hoe deze werken:

 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? 

Nog een voorbeeld van same :

 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 

Het bovenstaande voorbeeld maakt gebruik van alle 4 vormen van POSIX-parametervervanging en hun verschillende :colon null of not null tests. Er is meer informatie in de bovenstaande link, en hier is het weer .

Iets anders waar mensen vaak niet over nadenken over ${parameter:+expansion} is hoe nuttig het kan zijn in een here-document. Hier is nog een fragment uit een ander antwoord :

TOP

Hier kun je “enkele standaardinstellingen instellen en voorbereiden om ze af te drukken wanneer ze worden aangeroepen …

#!/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 

MIDDEN

Hier definieert u andere functies om uw afdrukfunctie aan te roepen op basis van hun resultaten …

 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 } 

BODEM

Je hebt het nu allemaal ingesteld, dus hier is waar je je resultaten zult uitvoeren en ophalen.

 _less_important_function : "${PLACE:="the cemetery"}" _more_important_function : "${RESULT:="regret it."}" _less_important_function 

RESULTATEN

Ik zal dadelijk ingaan op waarom, maar het uitvoeren van het bovenstaande levert de volgende resultaten op:

_less_important_function()"s eerste keer uitvoeren:

Ik ging naar het huis van je moeder en zag Disney on Ice.

Als je kalligrafie doet, zul je slagen.

th en _more_important_function():

Ik ging naar de begraafplaats en zag Disney on Ice.

Als je corrigerende wiskunde doet, zul je slagen.

_less_important_function() nogmaals:

Ik ging naar de begraafplaats en zag Disney on Ice.

Als u corrigerende wiskunde doet, zult u er spijt van krijgen.

HOE HET WERKT:

Het belangrijkste kenmerk hier is het concept van conditional ${parameter} expansion. U kunt een variabele instellen op een waarde alleen als deze niet is ingesteld of null is met behulp van het formulier:

${var_name : = desired_value}

Als u in plaats daarvan alleen een niet-ingestelde variabele wilt instellen, moet u de en null-waarden zouden blijven zoals ze zijn.

ON SCOPE:

Je zou kunnen opmerken dat in het bovenstaande voorbeeld $PLACE en $RESULT worden gewijzigd wanneer ingesteld via parameter expansion ook al is _top_of_script_pr() al aangeroepen, waarschijnlijk ingesteld wanneer het wordt uitgevoerd. De reden dat dit werkt is dat _top_of_script_pr() een ( subshelled ) functie is – ik heb ingesloten het in parens in plaats van de { curly braces } die voor de andere wordt gebruikt. Omdat het wordt aangeroepen in een subshell, is elke variabele die het instelt locally scoped en als het terugkeert naar de bovenliggende shell, verdwijnen die waarden.

Maar wanneer _more_important_function() instelt $ACTION is het globally scoped dus het beïnvloedt _less_important_function()"s tweede evaluatie van $ACTION omdat _less_important_function() $ACTION alleen instelt via ${parameter:=expansion}.

Reacties

  • Goed om te zien dat de steno-standaardwaarde werkt in Bourne Shell

Antwoord

Persoonlijke ervaring.

Ik gebruik dit formaat soms in mijn scripts om ad-hoc waarden te overschrijven, bijv.als ik:

$ cat script.sh SOMETHING="${SOMETHING:-something}"; echo "$SOMETHING"; 

Ik kan uitvoeren:

$ env SOMETHING="something other than the default value" ./script.sh` 

zonder te hoeven veranderen de oorspronkelijke standaardwaarde van SOMETHING.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *