Как реализовать СУХОЕ программирование с несколькими меню в Bash - PullRequest
1 голос
/ 28 июня 2019

В моем скрипте bash есть меню выбора, и мне было любопытно, есть ли способ упростить и сжать меню, не повторяя себя. Я пробовал много разных методов безрезультатно, кто-нибудь знает хороший способ сжать этот код:

    PS3="some menu"
    options=("option 1" "option2" "option3" "exit")
    select opt in "${options[@]}"
    do
        case $opt in
            "option1")
                something
                ;;
            "option 1")
                something
                ;;
            "option 2")
                something
                ;;
            "exit")

                ;;
            *) echo "invalid option $REPLY";;
        esac
        read -p "Press Enter to continue"
        clear
        return 1
    done

    PS3="some menu 2"
    options=("option 1" "option2" "exit")
    select opt in "${options[@]}"
    do
        case $opt in
            "option 1")
                something
                ;;
            "option 2")
                something
                ;;

            "exit")
                exit
                ;;
            *) echo "invalid option $REPLY";;
        esac
        read -p "Press Enter to continue"
        clear
        return 1
    done

Я хочу сжать этот код без повторения нескольких меню в моем коде.

Ответы [ 2 ]

1 голос
/ 28 июня 2019

Поместите его в функцию и вызовите его дважды, примерно так:

#!/usr/bin/env bash

prompt() {
    local opt
    local -A isExpected
    local -a options
    PS3="$1"
    shift
    options=()
    for opt; do
        isExpected["$opt"]=1
        options+=("$opt")
    done
    isExpected["exit"]=1
    options+=("exit")
    select opt in "${options[@]}"
    do
        if (( "${isExpected[$opt]}" )); then
            case $opt in
                "option 1")
                    something
                    ;;
               "option 2")
                    something
                    ;;
                "option 3")
                    something
                    ;;
                "exit")
                    ;;
                *) printf 'invalid option "%s"\n' "$REPLY" >&2;;
            esac
        else
            printf 'unexpected option "%s"\n' "$opt" >&2
        fi
        read -r -p "Press Enter to continue"
        clear
        return 1
    done
}

prompt "some menu" "option 1" "option 2" "option 3"
prompt "some menu 2" "option 1" "option 2"

Очевидно, что вы можете переместить все общие параметры в prompt(), как я это сделал для "exit". Если порядок представленных опций не имеет значения, тогда вы можете избавиться от isExpected[] и просто использовать один ассоциированный массив для хранения options и доступа для выбора, используя ${!options[@]}".

0 голосов
/ 28 июня 2019

Вы можете использовать таблицу диспетчеризации, сопоставляя текст опции с функцией для этой опции. Для использования local -n namerefs

требуется bash версии 4.4+.
fn_a1() { echo "do something here for option a1"; }
fn_a2() { echo "do something here for option a2"; }
fn_a3() { echo "do something here for option a3"; }
fn_b1() { echo "do something here for option b1"; }
fn_b2() { echo "do something here for option b2"; }

prompt() {
    local PS3="$1: "
    local -n _options=$2 _dispatch=$3
    select opt in "${_options[@]}"; do
        if [[ -v _dispatch["$opt"] ]]; then
            "${_dispatch[$opt]}"
            break
        fi
    done
}

declare -A dispatch_table
declare -a options

options=( "option a1" "option a2" "option a3" exit )
dispatch_table=(
    ["option a1"]=fn_a1
    ["option a2"]=fn_a2
    ["option a3"]=fn_a3
    ["exit"]=exit
)
prompt "some menu" options dispatch_table

options=( "option b1" "option b2" exit )
dispatch_table=(
    ["option b1"]=fn_b1
    ["option b2"]=fn_b2
    ["exit"]=exit
)
prompt "some menu 2" options dispatch_table

Я отправляю опции в виде отдельного массива, чтобы я мог управлять порядком меню: перебор ключей ассоциативного массива не имеет внутреннего порядка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...