如何从关联数组在 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

bashselect命令似乎没有生成我想要的菜单,因为我需要在菜单中显示两项信息: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

相关内容