Я хотел инициализировать некоторые строки в верхней части моего скрипта с переменными, которые еще не были установлены, например:
str1='I went to ${PLACE} and saw ${EVENT}'
str2='If you do ${ACTION} you will ${RESULT}'
а потом на PLACE
, EVENT
, ACTION
и RESULT
будет установлен. Затем я хочу распечатать мои строки с расширенными переменными. Это мой единственный вариант eval
? Это похоже на работу:
eval "echo ${str1}"
это стандарт? Есть лучший способ это сделать? Было бы неплохо не работать, eval
учитывая, что переменные могут быть чем угодно.
Поскольку я понимаю ваше значение, я не верю, что какой-либо из этих ответов является правильным.
eval
в этом нет необходимости, и вам даже не нужно даже дважды оценивать ваши переменные.Это правда, @Gilles подходит очень близко, но он не рассматривает проблему возможного переопределения значений и того, как они должны использоваться, если они вам нужны более одного раза. В конце концов, шаблон должен использоваться более одного раза, верно?
Я думаю, важен порядок, в котором вы оцениваете их. Учтите следующее:
ВЕРХ
Здесь вы установите некоторые значения по умолчанию и подготовитесь распечатать их при вызове ...
БЛИЖНИЙ
Здесь вы определяете другие функции для вызова вашей функции печати на основе их результатов ...
ДНО
Теперь у вас все настроено, так что вот где вы будете выполнять и извлекать результаты.
РЕЗУЛЬТАТЫ
Я пойду, почему через мгновение, но выполнение выше дает следующие результаты:
КАК ЭТО УСТРОЕНО:
Ключевой особенностью здесь является концепция «
conditional ${parameter} expansion.
Вы можете установить переменную в значение только в том случае, если она не установлена или равна нулю, используя форму:Если вместо этого вы захотите установить только неустановленную переменную, вы бы пропустили
: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}.
Это позволяет вам сделать это:
ЗДЕСЬ-ДОКУМЕНТЫ
И, между прочим, встроенное определение нулевой или неустановленной переменной также является причиной того, что работает следующее:
Лучший способ думать об этом
here-document
- это фактический файл, переданный во входной дескриптор файла. Более или менее это то, чем они являются, но разные оболочки реализуют их немного по-разному.В любом случае, если вы не заключите в кавычки значение,
<<LIMITER
вы получите его в потоковом режиме и оцените такимexpansion.
образом. Объявление переменной в банкеhere-document
может сработать, но только с помощьюexpansion
которой вы ограничиваете установку только тех переменных, которые еще не установлены. Тем не менее, это идеально соответствует вашим потребностям, как вы их описали, поскольку ваши значения по умолчанию всегда будут установлены при вызове функции печати шаблона.ПОЧЕМУ НЕТ
eval?
Хорошо, пример, который я представил, предоставляет безопасные и эффективные средства принятия.
parameters.
Поскольку он обрабатывает область действия, каждая переменная в наборе via${parameter:=expansion}
может быть определена извне. Итак, если вы поместите все это в скрипт с именем template_pr.sh и запустите:Вы получите:
Это не будет работать для тех переменных , которые были буквально установлены в сценарии, такие как
$EVENT, $ACTION,
и ,$one,
но я только определенных тем , таким образом , чтобы продемонстрировать разницу.В любом случае принятие неизвестных входных данных в
evaled
утверждение по своей сути небезопасно, тогда какparameter expansion
оно специально предназначено для этого.источник
Вы можете использовать заполнители для шаблонов строк вместо нерасширенных переменных. Это очень быстро запутается. Если то, что вы делаете, очень тяжело с шаблонами, вы можете рассмотреть язык с реальной библиотекой шаблонов.
Недостатком вышесказанного является то, что переменная шаблона должна быть ее собственным словом (например, вы не можете сделать это
"%prefix%foo"
). Это можно исправить с помощью некоторых модификаций или просто жестко закодировать переменную шаблона вместо того, чтобы она была динамической.источник