Bashループの「2D配列」アクセス

Bashループの「2D配列」アクセス

bash(macOSのバージョン3.2)では、次のような結果を出力する選択メニューを実装したいと思います。

Select a fruit:
  0  Nothing
  1  A banana
  2  An orange

ユーザーが項目を選択したら、関連するbashスクリプトを実行できるようにしたいです。これには2D配列のようなものが必要ですが、正しく覚えていればbashには存在しません。 1つの基本アレイ内で複数のアレイを使用することを検討しました。次に、ループを使用してユーザーにメニューを表示します。

#!/usr/bin/env bash

item_nothing=("0" "Nothing" "")
item_banana=("1" "A banana" "select_banana.sh")
item_orange=("2" "An orange" "select_orange.sh")
items=(
    "item_nothing"
    "item_banana"
    "item_orange"
)

printf "Select a fruit:\n"
for item in "${items[@]}"; do
    printf "$(\$$item[0])"
    printf "$(\$$item[1])\n"
    # $(\$$item[2])
done

スクリプトを実行すると、次の結果が表示されます。

Select a fruit:
./fruit_selection.sh: line 14: $item_nothing[0]: command not found
./fruit_selection.sh: line 15: $item_nothing[1]: command not found

./fruit_selection.sh: line 14: $item_banana[0]: command not found
./fruit_selection.sh: line 15: $item_banana[1]: command not found

./fruit_selection.sh: line 14: $item_orange[0]: command not found
./fruit_selection.sh: line 15: $item_orange[1]: command not found

何が間違っているのかわかりません。私が説明する内容を達成するためのソリューションはありますか?また、私が始めたよりも良い方法がある場合は、躊躇しないで提案してください。


編集:forループの解決策は次のとおりです。

#!/usr/bin/env bash

item_nothing=("0" "Nothing" "")
item_banana=("1" "A banana" "select_banana.sh")
item_orange=("2" "An orange" "select_orange.sh")
items=(
    "item_nothing"
    "item_banana"
    "item_orange"
)

printf "Select a fruit:\n"
for item in "${items[@]}"; do
    var_0=$item[0]
    var_1=$item[1]
    printf "  ${!var_0}  "
    printf "${!var_1}\n"

    # var_3=$item[3]
    # do something with this later "${!var_3}\n"
done

ベストアンサー1

私は各アイテムではなく、あなたが持っている各情報の配列を作成します。必要に応じて、行ではなく列を使用してください。また、ゼロから始めて番号を付けたい場合は、インデックスを明示的に保存する必要はありません。

これは、配列内のいくつかの果物名の使用をレンダリングし、他の配列のより短いコードまたはコマンド名に基づいて機能します。

# names and values, the order must be the same in every array 
item_names=(Nothing "A banana" "An orange")             # displayed to user
item_codes=(NIL BAN ORA)                       # for internal use
item_funcs=('' do_banana '')                   # names of functions called

# special function for bananas
do_banana() {
    echo "Banana function called"
}

# present choices and read entry
for (( i=0 ; i < ${#item_names[@]} ; i++ )) {
    printf "%2d %s\n" "$i" "${item_names[i]}" 
}
read num
# XXX: verify that 'num' contains a number and is in the range...

printf "You chose the fruit with code '%s'\n" "${item_codes[num]}"

# if there's a function connected to this fruit, call it
if [ "${item_funcs[num]}" ]; then
    "${item_funcs[num]}"        
fi

# or do something based on the chosen value
case "${item_codes[num]}" in
    NIL)  echo "do something for nothing" ;;
    BAN)  echo "do something for banana" ;;
    ORA)  echo "do something for orange" ;;
esac 

と入力すると、1選択した内容が印刷さBANれ、問い合わせの対応するブランチが実行され、バナナcase関数が呼び出されます。数字のみが含まれていることを確認しnum、既存のプロジェクトの範囲内にあることを確認する必要があります。

これらのパラメータを使用してコマンド全体を保存するのは簡単ではありません。各コマンドを正しく保存するには配列が必要なためです。これを行う必要がある場合は、このステートメントを使用するのが最善ですcase。望むより:変数に保存されたコマンドをどのように実行できますか?

おすすめ記事