シェル変数の展開とグロブの効果とその上での分割


18

この投稿には実際には2つの個別の質問が含まれていますが、それらをグループ化することで、より多くのコンテキストが得られると思います。私は変数の引用符についてこの質問をしましたが、そもそも変数の展開が何を意味するのかよくわかりません。だから私の最初の質問は:

  1. unix / linux speakの変数展開とは何ですか?

私の質問の2番目の部分は、次の用語に関連しています。

  1. glob
  2. スプリット

上記は何を意味し、変数展開にどのように影響しますか?元の質問への回答には、次のことが記載されています。

(リストコンテキストで)引用符がないことは、split + glob演算子と考えてください。

echo $ testがecho glob(split( "$ test"))のように。

私は直接の概念取り組む任意の答えを見つけることができませんでしたグロブ分割をではなく、直接、このように他の質問に答えるには、それらの用語を使用しています最近のもの


回答:


15

変数展開(標準的な用語はパラメーター展開であり、変数置換とも呼ばれます)は、基本的に変数をその値で置き換えることを意味します。より正確には、それは交換手段$VARIABLE構築物(又は${VARIABLE}又は${VARIABLE#TEXT}変数の値から構築されているいくつかの他のテキストまたは他の構築物)。この他のテキストは、変数の展開です。

拡張プロセスは次のとおりです。(一般的なケースについてのみ説明します。一部のシェル設定と拡張機能は動作を変更します。)

  1. 文字列である変数の値を取得します。変数が定義されていない場合は、空の文字列を使用します。
  2. コンストラクトに変換が含まれている場合は、それを適用します。たとえば、コンストラクトが${VARIABLE#TEXT}で、変数の値がで始まる場合、値の先頭からTEXT削除TEXTします。
  3. コンテキストが単一の単語を要求する場合(たとえば、二重引用符内、割り当ての右側、またはヒアドキュメント内)、ここで終了します。それ以外の場合は、次の手順に進みます。
  4. 空白の各シーケンスで値を個別の単語に分割します。(変数IFSは空白以外の文字で分割するように変更できます。)結果は文字列ではなく、文字列のリストになります。値に空白のみが含まれる場合、このリストは空になります。
  5. リストの各要素をファイル名のワイルドカードパターン、つまりglobとして扱います。パターンがいくつかのファイルと一致する場合、一致するファイル名のリストに置き換えられます。それ以外の場合は、そのまま残されます。

たとえば、変数にfooが含まれa* b* c*、現在のディレクトリにファイルbarbazおよびが含まれているとしますpaz。次に${foo#??}、次のように展開されます。

  1. 変数の値は8文字の文字列a* b* c*です。
  2. #??は、最初の2文字を取り除き、結果として6文字の文字列 b* c*(最初のスペースを含む)になることを意味します。
  3. 展開がリストコンテキストにある場合(つまり、二重引用符または他の同様のコンテキストにない場合)、続行します。
  4. 文字列を空白で区切られた単語に分割し、2つの文字列のリストを作成します:b*c*
  5. b*パターンとして解釈される文字列は、2つのファイルbarと一致します:およびbaz。文字列c*はファイルに一致しないため、そのまま残されます。結果は、3つの文字列のリストであります:barbazc*

たとえば、echo ${foo#??}prints bar baz c*(コマンドechoは引数を間にスペースを入れて結合します)。

詳細については、以下を参照してください。


2
それは呼ばれていますことを注意パラメータ展開、それが変数に適用されるため($var同様のパラメータの他のタイプ$1$#$?$-...
ステファンChazelas

12

グロブ/スプリット

まず、glob / splitを使用します。リンクした@Stephaneの回答は、一般的な意味でこれらの用語を使用しています。それらは実際のコマンドやそのようなものではなく、単なる擬似操作です。

split("$test")要素の「アレイ」に「$テスト」までの内容を分割します。

次にglob(...)*やなどのシェルグロビング文字を含むこれらの要素を展開するように注意します[1-2]

文字列$testは次のようになります。

$ test="afile[1-2] afile[3-5]"

また、いくつかのファイルを含むディレクトリがあるとします。

$ ls -1
afile1
afile2
afile3
afile4
afile5

引用符なしでそれをエコーし​​ようとすると、文字列がスペースで分割され、グロビング文字が展開されていることに気付くはずです。

$ echo $test
afile1 afile2 afile3 afile4 afile5

ただし、変数を引数として渡したときに変数を引用する場合はecho、元のリテラル文字列を取得します。

$ echo "$test"
afile[1-2] afile[3-5]

変数展開

変数展開という用語は、シェルがその基本操作の一部として実行している基本操作をカバーすることを意図しています。シェルは、入力を解析し、構文的に正しいと判断されたらこの入力を実行します。

前の例では。変数$testecho引用符なしで提示されたとき、シェルに先に進み、それらの引数を分割してからグロブするように指示していました。

引用されたとき、二重引用符でラップされた変数でその機能を本質的に無効にしました。

以下に、グロビングと分割のいくつかの追加例を示します。

glob / splittingは自動的に発生します

$ echo file{1..3}
file1 file2 file3

$ echo file{1..3} dir{a..b}
file1 file2 file3 dira dirb

$ echo dir{z..w} file{A..D}
dirz diry dirx dirw fileA fileB fileC fileD

$ echo dir{z..w} file{A..B} fileC
dirz diry dirx dirw fileA fileB fileC

二重引用符によるグロブ/分割は無効化

$ echo "dir{z..w} file{A..B} fileC"
dir{z..w} file{A..B} fileC

$ echo "dir{z..w} file{A..B}"
dir{z..w} file{A..B}

範囲が逆の順序で機能することも知りませんでした。
ジョー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.