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
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
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 potrzebujeszecho
. Ale jeśli nie ' t, wypróbuj:
wbudowany …: ${FOO:=default}
Twoje$FOO
jest ustawione nadefault
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
.
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. ”:-
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 „.