Bash配列の値を参照するときの[@]と[*]の違いは何ですか?

Bash配列の値を参照するときの[@]と[*]の違いは何ですか?

このバッシュガイド説明する:

インデックス番号がある場合、@または*配列のすべてのメンバーが参照されます。

私がこれを行うとき:

LIST=(1 2 3)
for i in "${LIST[@]}"; do
  echo "example.$i"
done

希望の結果を提供します。

example.1
example.2
example.3

しかし${LIST[*]}

example.1 2 3

代わりに。

なぜ?

編集:これは実際に使用するprintfと同じ結果を提供します。@*

答え1

違いは微妙です。"${LIST[*]}"(like "$*")は単一の引数を生成し、"${LIST[@]}"(like "$@")は各項目を別々の引数に拡張します。

LIST=(1 2 3)
for i in "${LIST[@]}"; do
    echo "example.$i"
done

リストを複数の変数として処理します(印刷)。

しかし:

LIST=(1 2 3)
for i in "${LIST[*]}"; do
    echo "example.$i"
done

リストは変数として扱われます。

答え2

使用すると[*]生成されます単一文字列、配列の各要素は、$IFS要素間の最初の文字に関連付けられます(デフォルトは空白)。

使用すると[@]生成されますリスト

例:

配列を作成します。

$ list=( a b "big fish" c d )

各要素を個別に印刷します。

$ printf 'data: ---%s---\n' "${list[@]}"
data: ---a---
data: ---b---
data: ---big fish---
data: ---c---
data: ---d---

単一の文字列を作成して印刷します。

$ printf 'data: ---%s---\n' "${list[*]}"
data: ---a b big fish c d---

繰り返しますが、カスタム区切り文字を使用すると、次のようになります。

$ IFS='/'
$ printf 'data: ---%s---\n' "${list[*]}"
data: ---a/b/big fish/c/d---

この拡張機能を使用する場合いいえ二重引用符はほとんど意味がありません。


の最初の文字がマルチバイト文字であるか、文字でデコードできない文字の場合、設定されていない$IFS場合(以降IFS=)、$IFS設定されていない場合(以降)には何もありませんが、その間に一部があります。シェルの違い。unset -v IFS$IFS

答え3

リスト要素にスペースなどの特殊文字が含まれていない単純なケースを考えてみましょう。その後、引用符を削除できます。その後、@と*は同じ結果を提供します。

LIST=(1 2 3)
for i in ${LIST[*]}; do
  echo "example.$i"
done

出力:

example.1
example.2
example.3

ここで、要素にスペースが含まれている場合を考えてみましょう。

LIST=(1 "a b" 3)
for i in ${LIST[*]}; do
  echo "example.$i"
done

この場合、@と*はまだ同じ結果を提供します。

example.1
example.a
example.b
example.3

しかし、「ab」は1つではなく2つの要素に分割されているので、これは私たちが望むものではありません。したがって、これを防ぐには引用符を使用する必要があります。

LIST=(1 "a b" 3)
for i in "${LIST[*]}"; do
  echo "example.$i"
done

しかし、それが判明しましたexample.1 a b 3。次に、*を@に変更します。

LIST=(1 "a b" 3)
for i in "${LIST[@]}"; do
  echo "example.$i"
done

最後に、我々は望む結果を得た。

example.1
example.a b
example.3

上記の結果を要約すると、@は引用符などの特定の演算子によって演算されたときに要素固有の演算を許可することがわかります。

関連情報