{a、b、c}がbashで展開されるのはいつですか?


13

を含むbashスクリプト

for i in {a,b}-{1,2}; do
  echo $i;
done

プリント

a-1
a-2
b-1
b-2

実行されたとき。これは私が期待したものです- {a,b}構造が拡張されているため。

ただし、(別の)スクリプトに次が含まれる場合

v={a,b}-{1,2}
echo $v

印刷する

{a,b}-{1,2}

それは私が期待したものではありません。私はそれが印刷されると思ったa-1 a-2 b-1 b-2。明らかに、{a,b}コンストラクトは展開されません。

私はそれをそのように拡張させることができます

v=$(echo {a,b}-{1,2})

これらの観察に基づいて、2つの質問があります。1){a,b}コンストラクトはいつ拡張されますか?2)$(echo {a,b}-{1,2})必要に応じて拡張をトリガーするのに好ましい方法はありますか?


1
これは、少なくとも、単純なで配列変数を作成できないという事実と一致しています=。たとえば、機能しv=a-1 a-2ません。
-grochmal

@grochmal-スカラー値を割り当てているためです。 v=a-1 a-2assign 'a-1' to variable v and run 'a-2' v=(a-1 a-2)、配列をvariableに割り当てることを意味しますvv+=(b-1 b-2)それに追加します。
cas

回答:


15

Bashのマニュアルは、と言っています:

SIMPLE COMMAND EXPANSION
When a simple command is executed, the shell performs the following
expansions, assignments, and redirections, from left to right.
[...]
4. The  text  after the = in each variable assignment undergoes tilde
   expansion, parameter expansion, command substitution, arithmetic
   expansion, and quote removal before being assigned to the variable.

中括弧の展開はリストにないため、割り当てに対しては実行されませんv={a,b}-{1,2}。@Wildcardで述べたように、v=a-1 v=b-1 ...とにかく単純な拡張は無意味です。

また、を実行するecho $vと、次のことが適用されます。

EXPANSION
Expansion is performed on the command line after it has been split
into words. [...]

The order of expansions is: brace expansion; tilde expansion, 
parameter and variable expansion, arithmetic expansion, and command
substitution (done in a left-to-right fashion); word splitting; and
pathname expansion.

中括弧の展開は変数の展開の前に行われるため、割り当てられた中括弧$vは展開されません。

ただし、次のようなことができます。

$ var_this=foo var_that=bar
$ echo $var_{this,that}
foo bar

展開する$(echo ...)文字列に空白がない場合は、を使用して展開すると機能するため、単語分割で問題が発生することはありません。より良い方法は、可能であれば配列変数を使用することです。

たとえば、展開を配列に保存し、展開された値を使用してコマンドを実行します。

$ v=( {a,b}-{1,2} )
$ some_command "${v[@]}"

5

興味深い点。以下からの抜粋が役立つ可能性がありますman bash

変数は、フォームの文でに割り当てることができ、

      名前 = [ ]

が指定されていない場合、変数にはヌル文字列が割り当てられます。すべてのは、チルダ展開、パラメーターと変数の展開、コマンド置換、算術展開、および引用符の削除(以下の拡張を参照)を受けます。

リストの中括弧の拡張は言及されていないことに注意してください。

しかし、これはまだ疑問を残しています:シェルは、これが変数の割り当てであり、したがってブレース展開の対象ではないことをどのように知っていますか?または、より正確には、ブレース展開を処理する前に変数の割り当てを識別するためにシェルが定義されるように、解析シーケンスはどこで明確化および成文化されていますか?(これは明らかに動作する方法ですがbash、これを説明するドキュメントの正確な行を見つけていません。)


1
たぶんこれ?「2.変数の割り当てまたはリダイレクトではない単語は展開されます(シェル展開を参照)。」
ジェフシャラー

@JeffSchaller、あなたは正しい。実際、この質問に対する答えは、「単純なコマンド拡張」セクション(LESS=+/SIMPLE man bash)を読むだけです。
ワイルドカード

0

私のlilの知識によると、{a、b、c}は直接エコーされるかコマンドで使用されると展開されます。例:mkdir〜/ {a、b、c}それをエコーするか、引数として使用します!

u@h:~$ echo {a,b}-{1,2}
a-1 a-2 b-1 b-2
u@h:~$ v={a,b}-{1,2}
u@h:~$ echo $v
{a,b}-{1,2}
u@h:~$ eval echo $v
a-1 a-2 b-1 b-2

"a"の後にアルファ順[az]の "b"があり、 "1"の後に12進数[0-9]の "2"があるため、コンマ "の二重ピリオド" .. "を使用できます。 」

u@h:~$ echo {a..b}-{1..2}
a-1 a-2 b-1 b-2
u@h:~$ v={a..b}-{1..2}
u@h:~$ echo $v
{a..b}-{1..2}
u@h:~$ eval echo $v
a-1 a-2 b-1 b-2

1
問題は、リテラル文字列「a-1 a-2 b-1 b-2」に設定さvなかった理由です。または、少なくとも、次のコマンドを入力してもエラーがスローされなかったのはなぜですか(変数の割り当てが展開されると予想されます)。いい質問です。これは実際には答えません。v=a-1 v=a-2 v=b-1 v=b-2
ワイルドカード

@SatoKatsura、「ワイルドカード拡張」とはどういう意味ですか?パラメーターの展開、パス名の展開、およびブレースの展開があります。これらはいずれも参照することができ、すべてが異なります。それとも、単語の分割を意味しましたか?
ワイルドカード

0

bashの変数に割り当てても、式は展開されません。

この小さなスクリプトについては、xが含まれています"*"の展開をしていません"*"

#!/bin/bash
x=*
echo "$x"

ただし、一部の値は展開されます、ref。イルカチュウからのいい答え。

式は評価されるときに展開されます。

このような:

x=$(echo *)        # <-- evaluation of "*"
echo "$x"

またはこのように:

x=*
echo $x            # <-- evaluation of $x

またはこのように:

x=*
eval echo "$x"     # <-- evaluation of `echo *`

トリガー$()はかなり一般的で、私はそれが好ましいと思いevalますが、変数が実際にコマンドで使用されるまで、評価をトリガーしないことがおそらく最善です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.