Chciałem zainicjować niektóre ciągi na początku mojego skryptu za pomocą zmiennych, które nie zostały jeszcze ustawione, takich jak:
str1='I went to ${PLACE} and saw ${EVENT}'
str2='If you do ${ACTION} you will ${RESULT}'
a później na PLACE
, EVENT
, ACTION
, i RESULT
będzie ustawiony. Chcę wtedy móc wydrukować moje łańcuchy z rozwiniętymi zmiennymi. Czy moja jedyna opcja eval
? To wydaje się działać:
eval "echo ${str1}"
czy to standard? czy jest na to lepszy sposób? Byłoby miło nie uruchamiać, eval
ponieważ zmienne mogą być cokolwiek.
Biorąc pod uwagę twoje znaczenie, nie sądzę, aby którakolwiek z tych odpowiedzi była poprawna.
eval
nie jest w żaden sposób konieczne, ani nie musisz nawet dwukrotnie oceniać swoich zmiennych.To prawda, @Gilles jest bardzo blisko, ale nie rozwiązuje problemu potencjalnie nadpisujących wartości i tego, jak należy ich używać, jeśli potrzebujesz ich więcej niż jeden raz. W końcu szablon powinien być używany więcej niż raz, prawda?
Myślę, że ważniejsza jest kolejność ich oceniania. Rozważ następujące:
TOP
Tutaj ustawisz niektóre wartości domyślne i przygotujesz się do ich wydrukowania po wywołaniu ...
ŚRODKOWY
Tutaj definiujesz inne funkcje, które mają być wywoływane w funkcji drukowania na podstawie ich wyników ...
DOLNY
Masz już wszystko skonfigurowane, więc tutaj wykonasz i wyciągniesz wyniki.
WYNIKI
Zaraz się zastanowię, dlaczego, ale uruchomienie powyższego daje następujące wyniki:
JAK TO DZIAŁA:
Kluczową cechą tutaj jest koncepcja
conditional ${parameter} expansion.
Można ustawić zmienną na wartość tylko wtedy, gdy jest ona nieustawiona lub zerowa przy użyciu formularza:Jeśli zamiast tego chcesz ustawić tylko zmienną nieuzbrojoną, pominiesz,
:colon
a wartości null pozostaną bez zmian.W ZAKRESIE:
Możesz zauważyć to w powyższym przykładzie
$PLACE
i$RESULT
zmienić się po ustawieniu za pośrednictwem,parameter expansion
nawet jeśli_top_of_script_pr()
zostało już wywołane, prawdopodobnie ustawiając je po uruchomieniu. Powodem, dla którego to działa,_top_of_script_pr()
jest( subshelled )
funkcja - ja ją zawarłem,parens
a nie{ curly braces }
użyłem dla innych. Ponieważ jest wywoływana w podpowłoce, każda ustawiona przez nią zmienna jest,locally scoped
a po powrocie do powłoki macierzystej wartości te znikają.Ale kiedy
_more_important_function()
zestawy$ACTION
jestglobally scoped
więc wpływa na_less_important_function()'s
drugą ocenę$ACTION
ponieważ_less_important_function()
zestawów$ACTION
tylko poprzez${parameter:=expansion}.
:ZERO
I dlaczego używam wiodącej
:colon?
Cóż,man
strona powie ci, że: does nothing, gracefully.
widzisz,parameter expansion
jest dokładnie tak, jak to brzmi -expands
do wartości${parameter}.
So Więc kiedy ustawimy zmienną${parameter:=expansion}
, pozostanie nam jej wartość - którą powłoka będzie próba wykonania in-line. Gdyby próbował uruchomićthe cemetery
, wyplułby na ciebie kilka błędów.PLACE="${PLACE:="the cemetery"}"
przyniosłoby takie same wyniki, ale w tym przypadku jest również zbędne i wolałem powłokę: ${did:=nothing, gracefully}.
Pozwala ci to zrobić:
TUTAJ DOKUMENTY
Nawiasem mówiąc - wbudowana definicja zmiennej zerowej lub nieuzbrojonej jest również przyczyną następujących działań:
Najlepszym sposobem, aby myśleć o tym,
here-document
jest rzeczywisty plik przesyłany strumieniowo do deskryptora pliku wejściowego. Mniej więcej takie są, ale różne powłoki implementują je nieco inaczej.W każdym razie, jeśli nie zacytujesz
<<LIMITER
, dostajesz go strumieniowo i oceniasz pod kątemexpansion.
Więc zadeklarowanie zmiennej where-document
puszce może działać, ale tylko przez toexpansion
ogranicza cię do ustawiania tylko zmiennych, które nie są jeszcze ustawione. Mimo to idealnie odpowiada Twoim potrzebom, tak jak je opisałeś, ponieważ domyślne wartości będą zawsze ustawione po wywołaniu funkcji drukowania szablonu.DLACZEGO NIE
eval?
Cóż, przykład, który przedstawiłem, zapewnia bezpieczny i skuteczny sposób akceptacji
parameters.
Ponieważ obsługuje zakres, każdą zmienną w zestawie${parameter:=expansion}
można definiować z zewnątrz. Jeśli więc umieścisz to wszystko w skrypcie o nazwie template_pr.sh i uruchomisz:Dostałbyś:
Nie działałoby to dla tych zmiennych, które zostały dosłownie ustawione w skrypcie, takich jak
$EVENT, $ACTION,
i,$one,
ale zdefiniowałem je tylko w ten sposób, aby pokazać różnicę.W każdym razie akceptacja nieznanych danych wejściowych w
evaled
instrukcji jest z natury niebezpieczna, podczas gdyparameter expansion
jest specjalnie zaprojektowana do tego.źródło
Można używać symboli zastępczych dla szablonów ciągów zamiast nierozwiniętych zmiennych. Szybko się zepsuje. Jeśli to, co robisz, jest bardzo obciążone szablonami, możesz rozważyć język z prawdziwą biblioteką szablonów.
Minusem powyższego jest to, że zmienna szablonu musi być własnym słowem (np. Nie możesz tego zrobić
"%prefix%foo"
). Można to naprawić za pomocą pewnych modyfikacji lub po prostu przez stałe zakodowanie zmiennej szablonu zamiast dynamicznej.źródło