私はコマンドの置き換えを理解しています。私はサブシェルを理解しています。サブシェルを使用すると、配列の構造が変わる理由を理解できません。
次のコマンド出力を提供します。 (openstackコマンドの使用は関係ありません)
bash$ floating ip list -c 'Floating IP Address' -f value
172.25.250.106
172.25.250.107
172.25.250.101
配列からキャプチャしようとしましたが、すべてのアドレスは要素0で終わります。
bash$ float=$( openstack floating ip list -c 'Floating IP Address' -f value )
bash$ echo ${float[@]}
172.25.250.106 172.25.250.107 172.25.250.101
bash$ echo ${#float[@]}
1
bash$ echo ${float[0]}
172.25.250.106 172.25.250.107 172.25.250.101
bash$ echo ${#float[0]}
44
完全な出力は文字列としてキャプチャされ、要素として解析されません。私はすべての単語が一つの要素になることを期待しています。各IPアドレスが参照されていることを確認するためにこの操作を繰り返す(-f値の代わりに-f csvを使用)、結果は同じです。
次に、コマンド置換をサブシェルに入れます。
bash$ unset float
bash$ float=( $( openstack floating ip list -c 'Floating IP Address' -f value ) )
bash$ echo ${float[@]}
172.25.250.106 172.25.250.107 172.25.250.101
bash$ echo ${#float[@]}
3
echo ${float[0]}
172.25.250.106
echo ${#float[0]}
14
これが私がもともと期待していた動作です。また、配列を構築するためにread文を使用することが期待どおりに機能することを確認しました。
bash$ unset float
bash$ read -a float <<< $( openstack floating ip list -c 'Floating IP Address' -f value )
bash$ echo ${float[@]}
172.25.250.106 172.25.250.107 172.25.250.101
bash$ echo ${#float[@]}
3
echo ${float[0]}
172.25.250.106
echo ${#float[0]}
14
元のコマンド置換操作を見たいです。フィールド区切り文字を最初に設定する必要があるのか、それとも何かが欠けているのだろうか。私は行動の違いを引き起こす原因を理解しようとしています。
ベストアンサー1
float=$( openstack floating ip list -c 'Floating IP Address' -f value )
これはひも配列変数ではなく変数です。文字列は、末尾の改行を引いたコマンドの出力です。
文字列変数を配列として使用しようとすると、位置0に文字列値を持つ単一要素配列として扱われます。
float=( $( openstack floating ip list -c 'Floating IP Address' -f value ) )
これは、「コマンド置換をサブシェルに入れる」ことではありません。コマンド置換自体が$(…)
サブシェルを生成します。周囲の括弧は、他のサブシェルを生成せずに配列を生成します。配列の内容はコマンドの出力を取り、末尾の改行を削除し、スペースで区切られた単語のリストに分割し、1つ以上のファイルに一致するワイルドカードを含むこのリストのすべての要素に一致するファイル名のリストで置き換えて得ます。
コマンドが予想される場所に角かっこを配置すると、サブシェルが生成されます。でvar=(…)
等号の後に続くのは、コマンドではなく割り当てられた値です。この場合、角括弧は値が配列であることを示します。