Używanie “ $ {a: -b} ” do przypisywania zmiennych w skryptach

Patrzyłem na kilka skryptów napisanych przez innych ludzi (szczególnie Red Hat) i wiele z ich zmiennych jest przypisywanych przy użyciu następującej notacji VARIABLE1="${VARIABLE1:-some_val}" lub niektórych innych zmienne VARIABLE2="${VARIABLE2:-`echo $VARIABLE1`}"

Jaki jest sens używania tej notacji zamiast po prostu deklarowania wartości bezpośrednio (np. VARIABLE1=some_val )?

Czy ta notacja ma zalety lub są możliwe błędy, którym można by zapobiec?

Czy :- ma określone znaczenie w tym kontekście ?

Komentarze

  • Spójrz na man bash; wyszukaj blok ” Rozszerzenie parametru ” (przy około 28%). Te zadania to np. funkcje domyślne: ” Użyj wartości domyślnej tylko wtedy, gdy żadna nie została jeszcze ustawiona. ”
  • As :- ustawia wartość domyślną, :+ służy do zmiany wartości , jeśli zmienna jest Nie jest zerem. Na przykład. v=option; cmd ${v:+ with $v} Będzie działać ” cmd z opcją „. Ale jeśli $ v ma wartość null, uruchomiłoby się tylko ” cmd „.

Odpowiedź

Technika ta umożliwia przypisanie zmiennej wartości, jeśli inna zmienna jest pusta lub nieokreślona. UWAGA: Ta „inna zmienna” może być tą samą lub inną zmienną.

fragment

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

UWAGA: To formularz również działa, ${parameter-word}. Jeśli chcesz zobaczyć pełną listę wszystkich form rozszerzania parametrów dostępnych w Bash, zdecydowanie sugeruję, abyś przyjrzał się temu tematowi na wiki Bash Hacker zatytułowanej: „ Rozszerzanie parametrów „.

Przykłady

zmienna nie istnieje

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

zmienna istnieje

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

To samo można zrobić, oceniając inne zmienne lub uruchamiając polecenia w domyślnej części notacji zawierającej wartość.

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

Więcej przykładów

Możesz również użyć nieco innej notacji, w której jest to po prostu VARX=${VARX-<def. value>}.

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

Powyżej $VAR1 & $VAR2 zostały już zdefiniowane za pomocą ciągu „ma inną wartość”, ale $VAR3 było niezdefiniowane, więc zamiast tego użyto wartości domyślnej, 0.

Inny przykład

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

Sprawdzanie i przypisywanie przy użyciu := notacji

Na koniec wspomnę o poręcznym operatorze, :=. Spowoduje to sprawdzenie i przypisanie wartości, jeśli testowana zmienna jest pusta lub niezdefiniowana.

Przykład

Zauważ, że $VAR1 jest teraz zestaw. Operator := wykonał test i przypisanie w jednej operacji.

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

Jednak jeśli wartość jest ustawiona wcześniej, to pozostaje w spokoju.

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

Handy Dandy Reference Table

        ss tabeli

Referencje

Comments

  • Należy pamiętać, że nie wszystkie z tych rozszerzeń są udokumentowane w bash. ${var:-word} w Q to, ale nie ${var-word} powyżej. POSIX dokumentacja ma ładną tabelę, warto ją skopiować do th to odpowiedź – pubs.opengroup.org/onlinepubs/9699919799/utilities/…
  • @Graeme, jest to udokumentowane, wystarczy zwrócić uwagę na Pominięcie dwukropka powoduje test tylko dla nieustawionego parametru.
  • Używanie echo "${FOO:=default}" jest świetny, jeśli faktycznie potrzebujesz echo. Ale jeśli nie ' t, wypróbuj : wbudowany … : ${FOO:=default} Twoje $FOO jest ustawione na default jak powyżej (tj. Jeśli nie zostało jeszcze ustawione). Ale ' nie ma echa $FOO w trakcie.
  • OK, znalazłem odpowiedź: stackoverflow.com / q / 24405606/1172302 . Użycie ${4:-$VAR} zadziała.
  • +1 tylko w celu uzyskania szczegółowej odpowiedzi. Ale także dlatego, że odwołujesz się do doskonałej wiki bash. A także za to, że podajesz przykłady i tabelę. Do diabła, tylko + 1-ki aż do końca 🙂 Jeśli chodzi o mnie, składnia była prawie poprawna, ale nie do końca – po prostu nie ' nie przejmowałem się wystarczająco, aby przeszukać stronę podręcznika ale nie mogłem ' nie pamiętam, pod jakim nagłówkiem był, i ' nie śpię od 4 rano :() ..

Odpowiedź

@slm zawiera już dokumenty POSIX – które są bardzo pomocne – ale tak naprawdę nie rozwijają tego, jak te parametry mogą być łączone, aby wpływać na siebie nawzajem. Nie ma tu jeszcze wzmianki o tym formularzu:

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

To jest fragment z innej mojej odpowiedzi i myślę, że bardzo dobrze pokazuje, jak one działają:

 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? 

Inny przykład z to samo :

 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 

Powyższy przykład wykorzystuje wszystkie 4 formy podstawiania parametrów POSIX i ich różne testy :colon null lub not null . W powyższym linku znajduje się więcej informacji, a znowu tutaj .

Kolejną rzeczą, o której ludzie często nie biorą pod uwagę ${parameter:+expansion}, jest to, jak bardzo przydatne może to być w dokumencie tutaj. Oto kolejny fragment z inna odpowiedź :

TOP

Tutaj „ustawisz kilka ustawień domyślnych i przygotujesz się do ich wydrukowania po wywołaniu …

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

ŚRODKOWY

Tutaj definiujesz inne funkcje do wywołania funkcji drukowania na podstawie ich wyników …

 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

Masz już wszystko skonfigurowane, więc oto, gdzie możesz wykonać i pobrać wyniki.

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

WYNIKI

Za chwilę wyjaśnię, dlaczego, ale wykonanie powyższego daje następujące wyniki:

_less_important_function()"s pierwsze uruchomienie:

Poszedłem do domu Twojej matki i zobaczyłem Disney on Ice.

Jeśli wykonujesz kaligrafię , odniesiesz sukces.

th pl _more_important_function():

Poszedłem na cmentarz i zobaczyłem Disney on Ice.

Jeśli zastosujesz matematykę naprawczą , odniesiesz sukces.

_less_important_function() jeszcze raz:

Poszedłem na cmentarz i zobaczyłem Disney on Ice.

Jeśli zajmujesz się matematyką naprawczą, będziesz tego żałować.

JAK TO DZIAŁA:

Kluczową cechą jest tutaj koncepcja conditional ${parameter} expansion. Możesz ustawić zmienną na wartość tylko wtedy, gdy jest nieustawiona lub zerowa przy użyciu postaci:

${var_name : = desired_value}

Jeśli zamiast tego chcesz ustawić tylko nieustawioną zmienną, pomiń i wartości null pozostaną niezmienione.

ON SCOPE:

Możesz zauważyć, że w powyższym przykładzie $PLACE i $RESULT ulegają zmianie po ustawieniu za pomocą parameter expansion mimo że _top_of_script_pr() został już wywołany, przypuszczalnie ustawiając je podczas uruchamiania. Powodem tego jest to, że _top_of_script_pr() jest funkcją ( subshelled ) – załączyłem jest w parens zamiast w { curly braces } używanym w innych. Ponieważ jest wywoływana w podpowłoce, każda ustawiana przez nią zmienna jest locally scoped i gdy powraca do swojej powłoki nadrzędnej, te wartości znikają.

Ale kiedy _more_important_function() ustawia $ACTION to jest globally scoped , więc wpływa na _less_important_function()"s drugą ocenę $ACTION ponieważ _less_important_function() ustawia $ACTION tylko za pośrednictwem ${parameter:=expansion}.

Komentarze

  • Dobrze widzieć, że domyślna skrócona wartość działa w Bourne Shell

Odpowiedź

Osobiste doświadczenie.

Czasami używam tego formatu w moich skryptach, aby nadpisywać wartości ad hoc, np.jeśli mam:

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

Mogę uruchomić:

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

bez konieczności zmiany oryginalna domyślna wartość SOMETHING.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *