Оскільки я сприймаю ваше значення, я не вважаю, що будь-яка з цих відповідей є правильною. 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
}
BOTTOM
Зараз у вас все налаштовано, тому ось, де ви будете виконувати та виводити свої результати.
_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}.
:НУЛЬ
І чому я використовую провідний :colon?Ну, на manсторінці буде сказано, що : does nothing, gracefully.Ви бачите, parameter expansionсаме так воно і звучить - це expandsзначення Значення. ${parameter}.Отже, коли ми встановлюємо змінну, ${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.So, декларування змінної у документі here-documentможе працювати, але лише через те, expansionщо обмежує встановлення лише змінних, які вже не встановлені. Однак це абсолютно відповідає вашим потребам так, як ви їх описали, оскільки значення за замовчуванням завжди будуть встановлені під час виклику функції друку шаблону.
ЧОМУ НІ eval?
Що ж, приклад, який я представив, пропонує безпечний та ефективний спосіб прийняття, parameters.оскільки він обробляє область, кожна змінна, що знаходиться в наборі через ${parameter:=expansion}, визначається ззовні. Отже, якщо ви помістите все це в сценарій під назвою template_pr.sh і запустили:
% RESULT=something_else template_pr.sh
Ви отримаєте:
Я зайшов до будинку вашої матері і побачив Діснея на льоду
Якщо ви зробите каліграфію, ви будете щось_забагато
Я пішов на кладовище і побачив Діснея на льоду
Якщо ви займаєтеся корекційною математикою, ви будете щось цікавіти
Я пішов на кладовище і побачив Діснея на льоду
Якщо ви займаєтеся корекційною математикою, ви будете щось цікавіти
Це не буде працювати для тих змінних , які були буквально встановлені в сценарії, такі як $EVENT, $ACTION,і , $one,але я тільки певних тем , таким чином , щоб продемонструвати різницю.
У будь-якому випадку, прийняття невідомого вводу у evaledвиписку за своєю суттю є небезпечним, тоді parameter expansionяк розроблено спеціально для цього.