Поскольку я понимаю ваше значение, я не верю, что какой-либо из этих ответов является правильным. evalв этом нет необходимости, и вам даже не нужно даже дважды оценивать ваши переменные.
Это правда, @Gilles подходит очень близко, но он не рассматривает проблему возможного переопределения значений и того, как они должны использоваться, если они вам нужны более одного раза. В конце концов, шаблон должен использоваться более одного раза, верно?
Я думаю, важен порядок, в котором вы оцениваете их. Учтите следующее:
ВЕРХ
Здесь вы установите некоторые значения по умолчанию и подготовитесь распечатать их при вызове ...
#!/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
БЛИЖНИЙ
Здесь вы определяете другие функции для вызова вашей функции печати на основе их результатов ...
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
}
ДНО
Теперь у вас все настроено, так что вот где вы будете выполнять и извлекать результаты.
_less_important_function
: "${PLACE:="the cemetery"}"
_more_important_function
: "${RESULT:="regret it."}"
_less_important_function
РЕЗУЛЬТАТЫ
Я пойду, почему через мгновение, но выполнение выше дает следующие результаты:
_less_important_function()'s первый забег:
Я пошел в дом твоей матери и увидел Диснея на льду.
Если вы будете заниматься каллиграфией, у вас все получится.
тогда _more_important_function():
Я пошел на кладбище и увидел Дисней на льду.
Если вы делаете корректирующую математику, у вас все получится.
_less_important_function() опять таки:
Я пошел на кладбище и увидел Дисней на льду.
Если вы занимаетесь коррективной математикой, вы об этом пожалеете.
КАК ЭТО УСТРОЕНО:
Ключевой особенностью здесь является концепция « conditional ${parameter} expansion.Вы можете установить переменную в значение только в том случае, если она не установлена или равна нулю, используя форму:
${var_nameзнак равноdesired_value}
Если вместо этого вы захотите установить только неустановленную переменную, вы бы пропустили :colonзначения null и остались бы как есть.
НА ОБЛАСТИ:
Вы можете заметить это в приведенном выше примере $PLACEи $RESULTизменить его, если настроено через, parameter expansionхотя _top_of_script_pr()он уже был вызван, предположительно устанавливая их при запуске. Причина, по которой это работает, заключается в том, что _top_of_script_pr()это ( subshelled )функция - я включил ее, parensа не { curly braces }использовал для других. Поскольку он вызывается в подоболочке, каждая переменная, которую он устанавливает, имеет значение, locally scopedи при возврате в родительскую оболочку эти значения исчезают.
Но когда _more_important_function()наборы $ACTIONэто globally scopedтак, это влияет на _less_important_function()'sвторую оценку, $ACTIONпотому что _less_important_function()наборы $ACTIONтолько через${parameter:=expansion}.
:ЗНАЧЕНИЕ NULL
И почему я использую ведущий :colon?Ну, manстраница скажет вам, что : does nothing, gracefully.вы видите, parameter expansionэто именно то, на что это похоже - это expandsзначение ${parameter}.So. Когда мы устанавливаем переменную с, ${parameter:=expansion}мы остаемся с ее значением - что оболочка будет попытка выполнить в строке. Если бы он попытался запустить, the cemeteryон бы просто наплевал на вас. PLACE="${PLACE:="the cemetery"}"будет давать те же результаты, но это также избыточно в этом случае, и я предпочел, чтобы оболочка: ${did:=nothing, gracefully}.
Это позволяет вам сделать это:
echo ${var:=something or other}
echo $var
something or other
something or other
ЗДЕСЬ-ДОКУМЕНТЫ
И, между прочим, встроенное определение нулевой или неустановленной переменной также является причиной того, что работает следующее:
<<HEREDOC echo $yo
${yo=yoyo}
HEREDOC
yoyo
Лучший способ думать об этом here-document - это фактический файл, переданный во входной дескриптор файла. Более или менее это то, чем они являются, но разные оболочки реализуют их немного по-разному.
В любом случае, если вы не заключите в кавычки значение, <<LIMITERвы получите его в потоковом режиме и оцените таким expansion.образом. Объявление переменной в банке here-documentможет сработать, но только с помощью expansionкоторой вы ограничиваете установку только тех переменных, которые еще не установлены. Тем не менее, это идеально соответствует вашим потребностям, как вы их описали, поскольку ваши значения по умолчанию всегда будут установлены при вызове функции печати шаблона.
ПОЧЕМУ НЕТ eval?
Хорошо, пример, который я представил, предоставляет безопасные и эффективные средства принятия. parameters.Поскольку он обрабатывает область действия, каждая переменная в наборе via ${parameter:=expansion}может быть определена извне. Итак, если вы поместите все это в скрипт с именем template_pr.sh и запустите:
% RESULT=something_else template_pr.sh
Вы получите:
Я пошел в дом твоей матери и увидел Диснея на льду
Если вы будете заниматься каллиграфией, то будете
Я пошел на кладбище и увидел Дисней на льду
Если вы делаете корректирующую математику, вы будете что-то
Я пошел на кладбище и увидел Дисней на льду
Если вы делаете корректирующую математику, вы будете что-то
Это не будет работать для тех переменных , которые были буквально установлены в сценарии, такие как $EVENT, $ACTION,и , $one,но я только определенных тем , таким образом , чтобы продемонстрировать разницу.
В любом случае принятие неизвестных входных данных в evaledутверждение по своей сути небезопасно, тогда как parameter expansionоно специально предназначено для этого.