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


8

拡張置換は、シェルプログラミング言語の同じコンテキストで互換性があるようです。たとえば、BashリファレンスマニュアルBash Hackers Wikiなどの一部のドキュメントでは、「シェルパラメータ拡張」を説明するために「拡張」という単語を使用しています。しかし、他のいくつかの文書は「置換」という言葉を好むようです。Advanced Bash-Scripting Guideは、パラメータ置換を使用しています。

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


どちらも、例えば異なるコンテキストで有効ですvariable expansioncommand substitution。あなたの疑問は何ですか?
devnull 2014

特定のコンテキストがないと、これは広すぎ不明瞭だと思います。
devnull 14

bashのmanページを見ると、一般に「拡張」という言葉は、シェル内部のものだけが関係している場合に使用されているようですが、「置換」は、外部プロセスが関係しているものに適しているようです。
celtschk 2014

私のアドバイスを参考にすると、これらに完全に精通するまで、これらのドキュメントを読むのをやめることにman shなりman setます。そして、それを理解したら、シェル固有のドキュメントを作成します。
mikeserv 2014

@devnullそうですね。私はコンテキストにリンクを付けましたが、質問でコンテキストを明示的に指定する方が良いでしょう。質問がわかりやすくなるように編集します。
MS.Kim、2014

回答:


6

置換は、この意味での拡張とほぼ同義です。なぜなら、それらの意味が重複しているからです。どちらも完全に他の完全なサブカテゴリではありませんが、GNUマニュアルのセクションでは、全体的な拡張の一部と見なされる置換が参照されています。

膨張は、識別子の値を抽出します。例えば、もしthis=that私たちが展開したとき、this我々が得ますthat。置換を含まない展開は、使用済みの値がすでに存在し、単純に取得する必要があるという点で事前に決定されていますが、これには取得/明示的な値の組み合わせが含まれます(「算術展開」など)。

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

置換には、コマンドプロセスという 2つのフレーバーがあります。これらは対称的なものです。

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

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


  1. foo barこの場合、内部シェル関数である可能性があります。その場合、プロセス間IOはありません。シェル組み込みの存在は、この違いをそれほどはっきりと覆い隠します。コンテンツに関しては、入力と出力は同じになります。

私はこの説明が好きですが、操作の結果としてファイル名のセットを確実に生成するファイル名展開(マッチングアルゴリズム)をどのように二乗するのでしょうか。
De Novo

確かに、しかし意味論を果たすために、「識別子の値を抽出する」(私は拡張と呼んでいるもの)も操作ではなく、したがって置換ではありませんか?特に、「全体的な拡張の一部と見なされる置換がある」ためです。つまり、これらの単語間の関係は、左と右の違いに似ていません。ファイル名の拡張は、元の拡張の定義にうまく適合していると思いますが、そうではない理由をより明確にするために、上記の置換に関するものを明確にしました。
goldilocks

ファイル名の展開に関するこれ以外の直感的な説明を二乗したときの問題は、用語を独占的に定義したいということではありませんでしたが、そのファイル名の展開は、識別子にバインドされた値を取得していないようです。特定のシェル内では、特定のグロブの値はグロブだけではなく、同じグロブが異なるコンテキストで異なる出力を生成する可能性があります。さらに、後で取得するために値をバインドする必要はありません。関係は任意(foo = "whatever you're like"; echo "$ foo"など)ではなく、計算と結果です。
De Novo

算術展開における式と値の間の関係も(厳密に)任意ではないと思いますが、コンテキストに関係なく、特定の展開に対して値は1つだけです。私はただここでつまづいているかもしれませんが、この説明を考えると、すべてのシェル展開の中で、ファイル名の展開は奇妙な男のようです。
De Novo

2
set -- arg arg2
echo ${2+"$1"}
 #OUTPUT 
arg

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

 #there doesn't seem to be anything here

私は一般にその違いはごくわずかであり、注目に値するものではないと思います-用語はしばしば互換的に使用されます。ただし、上記の2つのケースを見ると、最初の例では、の展開の結果として代用さ $1$2ていることがわかります。拡張できないとすぐに代替はありません$2$2

goldilocksは、置換のエーテルの存在について良い点を示しています。シュレディンガーの猫のようなものだと思います。何かを思い出した。この形式の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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.