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 ...
#!/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, które mają być wywoływane w 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
}
DOLNY
Masz już wszystko skonfigurowane, więc tutaj wykonasz i wyciągniesz wyniki.
_less_important_function
: "${PLACE:="the cemetery"}"
_more_important_function
: "${RESULT:="regret it."}"
_less_important_function
WYNIKI
Zaraz się zastanowię, dlaczego, ale uruchomienie powyższego daje następujące wyniki:
_less_important_function()'s
pierwszy bieg:
Poszedłem do domu twojej matki i zobaczyłem Disneya na lodzie.
Jeśli wykonasz kaligrafię , odniesiesz sukces.
następnie _more_important_function():
Poszedłem na cmentarz i zobaczyłem Disneya na lodzie.
Jeśli wykonasz matematykę naprawczą , odniesiesz sukces.
_less_important_function()
jeszcze raz:
Poszedłem na cmentarz i zobaczyłem Disneya na lodzie.
Jeśli uczysz matematyki naprawczej, będziesz tego żałować.
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:
${var_name
: =desired_value}
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
jest globally 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ć:
echo ${var:=something or other}
echo $var
something or other
something or other
TUTAJ DOKUMENTY
Nawiasem mówiąc - wbudowana definicja zmiennej zerowej lub nieuzbrojonej jest również przyczyną następujących działań:
<<HEREDOC echo $yo
${yo=yoyo}
HEREDOC
yoyo
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ątem expansion.
Więc zadeklarowanie zmiennej w here-document
puszce może działać, ale tylko przez to expansion
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:
% RESULT=something_else template_pr.sh
Dostałbyś:
Poszedłem do domu twojej matki i zobaczyłem Disneya na lodzie
Jeśli wykonasz kaligrafię, zrobisz coś innego
Poszedłem na cmentarz i zobaczyłem Disneya na lodzie
Jeśli zajmujesz się matematyką zaradczą, zrobisz coś innego
Poszedłem na cmentarz i zobaczyłem Disneya na lodzie
Jeśli zajmujesz się matematyką zaradczą, zrobisz coś innego
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 gdy parameter expansion
jest specjalnie zaprojektowana do tego.