Bash 루프의 "2D 배열" 액세스

Bash 루프의 "2D 배열" 액세스

bash(macOS의 버전 3.2)에서 다음과 같은 결과를 출력하는 선택 메뉴를 구현하고 싶습니다.

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

사용자가 항목을 선택하면 관련 bash 스크립트를 실행할 수 있기를 원합니다. 이를 위해서는 2D 배열과 같은 것이 필요하지만 올바르게 기억한다면 그것은 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

나는 각 항목이 아닌 당신이 가지고 있는 각 정보에 대한 배열을 만들 것입니다. 원하는 경우 행이 아닌 열을 사용하세요. 또한 0부터 시작하여 번호를 매기려는 경우 인덱스를 명시적으로 저장할 필요가 없습니다.

이는 배열에서 일부 과일 이름의 사용을 렌더링하고 다른 배열의 더 짧은 코드 또는 명령 이름을 기반으로 작동합니다.

# 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. 바라보다:변수에 저장된 명령을 어떻게 실행할 수 있나요?

관련 정보