私はあなたの意味を理解しているので、これらの答えが正しいとは思いません。eval
決して必要ではありません。また、変数を2回評価する必要もありません。
確かに、@ 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.
の形式を使用して変数が設定されていないかnullである場合にのみ変数に値を設定できるという概念です。
${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?
Well を使用するのですか、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
こちらのドキュメント
ところで-nullまたは未設定の変数のインライン定義も、以下が機能する理由です:
<<HEREDOC echo $yo
${yo=yoyo}
HEREDOC
yoyo
を考える最良の方法here-document
は、入力ファイル記述子にストリーミングされる実際のファイルとしてです。多かれ少なかれそれは彼らのものですが、異なるシェルはそれらをわずかに異なって実装します。
いずれにせよ、引用符で囲まない場合、<<LIMITER
それをストリームして評価するexpansion.
ので、aで変数を宣言するhere-document
ことはできますが、それを介しexpansion
てのみ、まだ設定されていない変数のみを設定できます。それでも、テンプレートの印刷関数を呼び出すとデフォルト値が常に設定されるため、これは説明したとおりのニーズに完全に適合します。
何故なの eval?
さて、提示した例は、parameters.
スコープを処理するため、set via内のすべての変数${parameter:=expansion}
は外部から定義できるため、安全で効果的な受け入れ方法を提供します。したがって、これらすべてをtemplate_pr.shというスクリプトに入れて実行した場合:
% RESULT=something_else template_pr.sh
あなたが得るだろう:
私はあなたの母親の家に行き、ディズニー・オン・アイスを見ました
書道をすれば、something_else
墓地に行ってディズニー・オン・アイスを見た
修復数学を行うと、something_elseになります
墓地に行ってディズニー・オン・アイスを見た
修復数学を行うと、something_elseになります
これは、スクリプト内で文字通りに設定された変数やなどでは機能$EVENT, $ACTION,
し$one,
ませんが、違いを示すためにそのように定義しただけです。
いずれにせよ、evaled
ステートメントへの未知の入力の受け入れは本質的に安全ではありませんが、parameter expansion
そうするように特別に設計されています。