web-dev-qa-db-ja.com

配列のbash配列

いくつかのネストされたループを書き込もうとすると、その書き方がわかりません。多分私は間違った方向を見ていますが、私が書こうとしているのは:

declare -a bar=("alpha" "bravo" "charlie")
declare -a foo=("delta" "echo" "foxtrot" "golf")

declare -a subgroups=("bar" "foo")

それで私はサブグループを反復したいと思います(将来的にはbar sとfoo sが来るでしょう)、それらの中でそれらは異なる数を持つことができるのでそれらを反復します要素。

望ましい出力は次のようになります。

group name: bar with group members: alpha bravo charlie
        working on alpha of the bar group
        working on bravo of the bar group
        working on charlie of the bar group
group name: foo with group members: delta echo foxtrot golf
        working on delta of the foo group
        working on echo of the foo group
        working on foxtrot of the foo group
        working on golf of the foo group

私が書いたclosesコードはbarおよびfoo配列と、各セットの要素によるその拡張で失敗するようです。

for group in "${subgroups[@]}"; do
   lst=${!group}
   echo "group name: ${group} with group members: ${!lst[@]}"
   for element in "${!lst[@]}"; do
       echo -en "\tworking on $element of the $group group\n"
   done
done

そして出力は:

group name: bar with group members: 0
        working on 0 of the bar group
group name: foo with group members: 0
        working on 0 of the foo group
3
srgblnch

これは、bashでかなり一般的な問題であり、declare -nを使用して名前参照を作成する必要がある配列内の配列を参照することです。 -nに続く名前は、割り当てられた値の名前参照として機能します(=の後)。次に、この変数をnameref属性で扱い、配列であるかのように展開し、以前と同じように完全に引用符で囲まれた配列を展開します。

for group in "${subgroups[@]}"; do
    declare -n lst="$group"
    echo "group name: ${group} with group members: ${lst[@]}"
    for element in "${lst[@]}"; do
        echo -en "\tworking on $element of the $group group\n"
    done
done

bashは、v4.3以降のnamerefのみをサポートすることに注意してください。古いバージョンとその他の回避策については、 間接/参照変数の割り当て を参照してください。

4
Inian

スクリプトを正しく機能させるための最小限の変更は、次のようになります。

#!/bin/bash

declare -a bar=("alpha" "bravo" "charlie")
declare -a foo=("delta" "echo" "foxtrot" "golf")

declare -a groups=("bar" "foo")

for group in "${groups[@]}"; do
    lst="$group[@]"
    echo "group name: ${group} with group members: ${!lst}"
    for element in "${!lst}"; do
        echo -en "\tworking on $element of the $group group\n"
    done
done

主な変更点は次の2つです。

  • "${!lst[@]}"を使用しないでください。配列にアクセスするために"${!group[@]}"を使用しないでくださいelements。この構文は、配列onlyで配列indexesにアクセスします。

    ${!lst}"を使用してください。

  • 変数lstは、通常の${ }内に書き込むstringを含むように設定する必要があります。つまり、最初のレベルではlst=foo[@]で、配列の名前も間接的に必要な場合はlst="$group[@]"に設定します。変数groupの値。

    lst="$group[@]"
    

namerefsを使用した同等の構文には、値を展開するための!がありません(必要もありません)。
結果として、上記の[@]を削除する必要があります。

echo "using namerefs"

for group in "${groups[@]}"; do
    declare -n lst=$group
    echo "group name: ${group} with group members: ${lst[@]}"
    for element in "${lst[@]}"; do
        echo -en "\tworking on $element of the $group group\n"
    done
done
2
Isaac