bash 循环中的“二维数组”访问

bash 循环中的“二维数组”访问

我想在 bash(macOS 上的版本 3.2)中实现一个选择菜单,它将输出如下内容:

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

当用户选择一个项目时,我希望能够运行关联的 bash 脚本。为此,我需要类似二维数组的东西,但如果我没记错的话,它在 bash 中不存在。我考虑过在一个主数组中使用多个数组。然后我将使用循环向用户显示菜单:

#!/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语句。看:我们如何运行存储在变量中的命令?

相关内容