연관 배열을 사용하여 bash에서 간단한 메뉴를 만드는 방법

연관 배열을 사용하여 bash에서 간단한 메뉴를 만드는 방법

다음과 유사한 텍스트 메뉴를 표시하는 스크립트를 리팩터링하고 있습니다.

Select a mounted BTRFS device on your local machine to backup to.
1) 123456789abc-def012345-6789abcdef012 (/)
2) 123456789abc-def012345-6789abcdef012 (/home)
...
26) 3e3456789abc-def012345-6789abcdef369 (/mnt/backup2)
27) 223456789abc-def012345-6789abcdef246 (/mnt/backup3)

메뉴에는 UUID와 대상 경로라는 두 가지 정보가 표시됩니다.명령을 사용하여 복사하는 것은 select제가 어떻게 해야 할지 모르는 일 중 하나입니다.

이 메뉴에서 사용자는 숫자(예: 26)를 입력하고 스크립트는 장치 및 경로에 BTRFS 보내기 | 받기를 실행합니다. 스크립트 메뉴가 UUID와 경로를 표시하고 간단한 1~2자리 숫자 또는 문자 입력을 받아 동일한 방식으로 계속 작동하길 바랍니다.

그러나 코드를 리팩터링하고 싶습니다. 원래 코드를 작성하지 않았습니다. 두 개의 배열을 사용하여 메뉴를 표시하고 선택을 처리합니다.

연관배열을 사용하고 싶습니다. 이것은 순전히 연관 배열에 대한 경험을 쌓기 위한 연습입니다. 스크립트는 있는 그대로 실행됩니다.

메뉴의 기초로 작성한 다음 코드를 사용하고 싶습니다.

declare -A UUID_TARGETS

for target in $TARGETS; do
    if ! [[ "$target" =~ ^/mnt|^/backup ]] ; then
        echo "skipped $target"
    else
        UUID_TARGETS["$target"]=$(findmnt -n -t btrfs -o UUID -M "$target")
    fi
done

for target in "${!UUID_TARGETS[@]}"; do
    #testing
    echo UUID [${UUID_TARGETS["$target"]}] has mountpoint [$target]
done

bash select명령이 내가 원하는 메뉴를 생성하지 않는 것 같습니다.메뉴에 UUID와 대상 경로라는 두 가지 정보를 표시해야 합니다.. 이와 같은 순진한 사용만으로는 select충분하지 않습니다.

PS3="Please enter your choice (q to quit): "
select target in "${!UUID_TARGETS[@]}" "quit";
do
    case "$target" in
        "quit")
            echo "Exited"
            break
            ;;
        *)
            selected_uuid=${UUID_TARGETS["$target"]}
            selected_mnt="$target"
            ;;
    esac
done

여기 누군가가 있었으면 좋겠어연관 배열에서 이와 같은 메뉴를 만드는 우아한 솔루션. 추가 패키지 없이 bash에서 이 작업을 수행하고 싶습니다.

selected_uuid마지막으로 및 에 올바른 값을 할당 해야 합니다 selected_mnt. 원래 코드는 다음과 같이 구현됩니다.

selected_uuid="${UUIDS_ARRAY[$((disk))]}"
selected_mnt="${TARGETS_ARRAY[$((disk))]}"

참고로 원본 코드의 전체 섹션은 다음과 같습니다.

TARGETS="$(findmnt -n -l -t btrfs -o TARGET --list -F /etc/fstab)"
UUIDS="$(findmnt -n -l -t btrfs -o UUID --list -F /etc/fstab)"

declare -a TARGETS_ARRAY
declare -a UUIDS_ARRAY

i=0
disk=-1
disk_count=0
for x in $UUIDS; do
    UUIDS_ARRAY[$i]=$x
    if [[ "$x" == "$uuid_cmdline" ]]; then
        disk=$i
        disk_count=$(($disk_count+1))
    fi
    i=$((i+1))
done

i=0
for x in $TARGETS; do
    TARGETS_ARRAY[$i]=$x
    i=$((i+1))
done

if [[ "$disk_count" > 1 ]]; then
    disk="-1"
fi

if [[ "$disk" == -1 ]]; then
    if [[ "$disk_count" == 0 && "$uuid_cmdline" != "none" ]]; then
        error "A device with UUID $uuid_cmdline was not found to be mounted, or it is not a BTRFS device."
    fi
    if [[ -z $ssh ]]; then
        printf "Select a mounted BTRFS device on your local machine to backup to.\n"
    else
        printf "Select a mounted BTRFS device on $remote to backup to.\n"
    fi
    while [[ $disk -lt 0 || $disk -gt $i ]]; do
        for x in "${!TARGETS_ARRAY[@]}"; do
            printf "%4s) %s (%s)\n" "$((x+1))" "${UUIDS_ARRAY[$x]}" "${TARGETS_ARRAY[$x]}"
        done
        printf "%4s) Exit\n" "0"
        read -r -p "Enter a number: " disk
        if ! [[ $disk == ?(-)+([0-9]) ]]; then
            printf "\nNo disk selected. Select a disk to continue.\n"
            disk=-1
        fi
    done
    if [[ $disk == 0 ]]; then
        exit 0
    fi
    disk=$(($disk-1))
fi

selected_uuid="${UUIDS_ARRAY[$((disk))]}"
selected_mnt="${TARGETS_ARRAY[$((disk))]}"
printf "\nYou selected the disk with UUID %s.\n" "$selected_uuid" | tee $PIPE
printf "The disk is mounted at %s.\n" "$selected_mnt" | tee $PIPE

관련 정보