web-dev-qa-db-ja.com

シェルスクリプトの用語における拡張と置換の違い

ExpansionSubstitutionは、シェルプログラミング言語の同じコンテキストで交換可能のようです。たとえば、 BashリファレンスマニュアルBash Hackers Wiki などの一部のドキュメントでは、 'expansion'という単語を使用して 'シェルパラメータexpansion '。ただし、他のいくつかのドキュメントでは、「置換」という単語を好むようです。 Advanced Bash-Scripting Guide パラメーターsubstituionを使用します。

シェルプログラミングの用語に関して、「拡張」と「置換」の間に違いはありますか?

8
MS.Kim

Substitutionは、意味が重複しているため、このコンテキストではexpansionとほぼ同義です。 GNU Manual セクションでは、全体的な拡張の一部と見なされる置換がありますが、どちらももう一方の完全なサブカテゴリではありません。

expansionは識別子の値を抽出しています。たとえば、_this=that_の場合、thisを展開すると、thatが得られます。置換を伴わない拡張は、使用される値がすでに存在し、単に取得する必要があるという点で事前に決定されています。算術展開」)。

substitutionは、明示的な入出力操作の結果として値を作成します。たとえば、this=$(foo bar)の場合、thisは_foo bar_を実行し、その出力をキャプチャした結果です。1 置換の結果の値は完全に予測可能かもしれませんが、置換が行われるまで実際には存在しないため、通常の展開で取得される値とは異なります-生成されます。

置換には、commandprocessの2つのフレーバーがあり、これらは一種の対称的です。

_# Command substitution
foo=$(ls)
# Process substitution
wc <(ls)
_

最初の「コマンド」はlsであり、2番目の「プロセス」も同様です。置き換えられているのは、実際にはパイプの終わりであると言えます。プロセス置換はリダイレクトと重複しています。ただし、これはおそらく技術的には少し制限が多すぎるため、脚注に移動します...


  1. この場合の_foo bar_は、内部シェル関数である可能性があります。この場合、プロセス間IOはありません。 Shellビルトインの存在は、この違いをあまり明確に覆い隠しません。コンテンツに関しては、入力と出力は同じになります。
6
goldilocks
set -- arg arg2
echo ${2+"$1"}
 #OUTPUT 
arg

shift
echo ${2+"$1"}
 #OUTPUT

 #there doesn't seem to be anything here

違いは一般的に小さすぎて注目に値しないと思います-そしてこれらの用語はしばしば同じ意味で使用されます。ただし、上記の2つのケースを見ると、最初の例では、substitute$1 for $2であることがわかります。 $2展開の結果として。 $2展開できないとすぐに、置換はありません。

goldilocksは、Etherealの置換の存在について良い点を示しています。シュレディンガーの猫のようなものだと思います。それは私に何かを思い出させた。この形式のPOSIX指定のパラメーター展開に慣れていない場合もありますが、上記の形式とは逆の方法で機能します。

${var:?if $var is unset or null its \
     parent Shell dies and this message is output to stderr}

今度は同じ動作が必要ですが、set値が必要です。 POSIXは、その動作を正確に指定していません。しかし、1つか2つのトリックで、それは簡単に管理されます。

N= #N is null
var="any value should fail"
${var:+${N:?we substitute our \$Null var when \$var is expanded}}
  #OUTPUT
sh: line 3: N: we substitute our $Null var when $var is expanded

だが:

N= #N is null
var=
${var:+${N:?is never substituted}}
  #OUTPUT

#there doesn't seem to be anything here
2
mikeserv