tl;ディレクトリ
Bashでは、チルダ拡張の前に中括弧拡張が行われます。しかし、チルダプレフィックスは変数の割り当て前に拡張されているように見えますが、中括弧の拡張はそうではありません。なぜ?
詳細と例
サポート拡張Bashでは、以下で発生したものとして記録されます。チルダ拡張:
中括弧の拡張は、他の拡張の前に実行されます。
私が理解したのは、次の例のように、チルダ拡張が変数の割り当て前に発生します。
# UNQUOTED TILDE PREFIX, TILDE EXPANSION EXPECTED
tilde=~
echo "$tilde"
# /Users/DeNovo
[[ $tilde == "$HOME" ]] && echo "literal match"
# literal match
# QUOTED TILDE PREFIX, TILDE EXPANSION DOES NOT OCCUR
lit_tilde='~'
echo "$lit_tilde"
# ~
# UNQUOTED TILDE PREFIX PRODUCED AND EVALUATED, TILDE EXPANSION OCCURS
# AS EXPECTED
eval echo "$lit_tilde"
# /Users/DeNovo
[[ $lit_tilde == "~" ]] && echo "literal match"
# literal match
これらの例は、右オペランドがleft=right
左オペランドに値にバインドされる前にチルダ拡張を受けることを示すようです。
ただし、中括弧拡張は変数の割り当て前には行われず、リテラルチルダを変数にバインドするのと同様に機能します(拡張特殊文字/プレフィックスと比較して)。
# UNQUOTED BRACE, BUT NO EXPANSION. BRACE LITERAL IS PRESERVED
brace={a..c}
echo "$brace"
# {a..c}
[[ $brace = "a b c" ]] || echo "doesn't match"
# doesn't match
[[ $brace = "{a..c}" ]] && echo "literal match"
# literal match
# SIMILAR TO THE LITERAL TILDE, EVALUATING THE VARIABLE VALUE
# RESULTS IN BRACE EXPANSION
eval echo "$brace"
# a b c
両方の拡張を単一の例にまとめると、チルダ拡張が発生しますが、中かっこ拡張は発生しないことがわかります。
combined=~/dir_{a..c}
echo "$combined"
# /Users/DeNovo/dir_{a..c}
中括弧は、割り当て中に内部チルダが拡張されるのを防ぎます。
internal_tilde={~,~+}/new_dir
echo "$internal_tilde"
# {~,~+}/new_dir
# vs the same output, not in a variable
echo {~,~+}/new_dir
/Users/DeNovo/new_dir /Your/Working/Directory/new_dir
明確にするために、中括弧拡張の結果を含む変数を取得する方法を尋ねるのではなく、チルダ拡張の前に発生したにもかかわらず、変数の割り当て前に中括弧拡張が発生しない理由を尋ねることです。希望する動作を取得する方法はいくつかあります。これは:
# PROCESS SUBSTITUTION GIVES THE DESIRED BEHAVIOR
brace_exp="$(echo {a..c})"
echo "$brace_exp"
a b c
[[ $brace_exp = "a b c" ]] && echo "literal match"
# literal match
繰り返しますが、チルダ拡張はなぜ変数割り当ての前に発生しますが、中括弧拡張(チルダ拡張の前に発生する必要がある)は、変数割り当て前には発生しません。おそらくその使命は私が知らない何らかの点で特別なようです。
答え1
テストでは、{a..c}
拡張は変数の割り当ての一部であり、処理されるため、拡張はありません。それぞれ:
- パーサによって変数割り当てとしてマークされた単語(コマンド名の前の単語)とリダイレクトは、後で処理するために保存されます。
- 変数の割り当てやリダイレクトではない単語は拡張されます。シェル拡張)。拡張後に残りの単語がある場合、最初の単語はコマンド名として扱われ、残りの単語は引数として扱われます。
割り当てられた値は中括弧で拡張されません。
- 各変数の割り当てでは、 ""の後
=
に続くテキストは、変数に割り当てられる前にチルダ拡張、パラメータ拡張、コマンド置換、算術拡張、および引用符の削除を経ます。
答え2
@StephenKittの答えは、この動作が予想されることを示す関連文書(+1)を指します(なぜチルダプレフィックスは割り当て前に拡張されますが、中かっこは拡張されないのですか?それが定義された方法なので)。
回答:校正器の拡張が特別な理由の1つ、それが何であるかを見てみましょう。いいえ変数を割り当てると発生します。
- 支柱の拡張
- 単語分割(パーサーは行を分割しますが、その単語内で展開された結果は分割されません)
- ファイル名拡張子
拡張ワード数を変更できるタスクは次のとおりです。
中かっこ拡張、トークン化、およびファイル名拡張のみが拡張ワード数を変更できます。
例では、変数は配列ではなく文字列であり、1つの単語のみを含める必要があります。
サポート拡張するより複雑な例では、次のように配列が割り当てられたときに発生しますbrace=({a..c})
。
internal_tilde=({~,~+}/new_dir)
echo "${internal_tilde[@]}"
# /Users/DeNovo/new_dir /Your/Working/Directory/new_dir
したがって、私はこのデザインが(歴史的に奇妙ではありません)意味があると思います。チルダ拡張は単語数を変更しません。中かっこ拡張が実行されます。変数に複数の単語が含まれるようにするには、この目的のために特別に設計されたデータ構造を使用します。