bash - 選択と選択実行後に選択メニューを再表示する方法

bash - 選択と選択実行後に選択メニューを再表示する方法

アップデートの確認、テーマの再インストールという2つの機能を持つテーマ用のツールスクリプトを作成しています。

メニューを選択するコードは次のとおりです。

PS3='Choose an option: '
options=("Check for update" "Reinstall theme")
select opt in "${options[@]}"
do
     case $opt in
             "Check for update")
                       echo "Checking update"
                               ;;
             "Reinstall theme")
                       echo "Reinstalling"
                               ;;
                               *) echo invalid option;;
     esac
done

実行すると、これが発生します

1) Check for update
2) Reinstall theme
Choose an option:

1と入力してEnterを押して、更新コマンドの確認を実行します。

問題は、スクリプトの実行が終了すると、メニューの代わりに「オプションの選択:」が再び表示されることです。したがって、メニューがなければ、ユーザーは選択するのが難しいかもしれません(特に非常に長いスクリプトの後)。

1) Check for update
2) Reinstall theme
Choose an option: 1
Checking update
Choose an option:

では、オプションの実行後にメニューを再表示するにはどうすればよいですか?

答え1

私はあなたが本当に次のようなことをしたいと思います:

check_update () {
    echo "Checking update"
}

reinstall_theme () {
    echo "Reinstalling theme"
}

while true; do
    options=("Check for update" "Reinstall theme")

    echo "Choose an option:"
    select opt in "${options[@]}"; do
        case $REPLY in
            1) check_update; break ;;
            2) reinstall_theme; break ;;
            *) echo "What's that?" >&2
        esac
    done

    echo "Doing other things..."

    echo "Are we done?"
    select opt in "Yes" "No"; do
        case $REPLY in
            1) break 2 ;;
            2) break ;;
            *) echo "Look, it's a simple question..." >&2
        esac
    done
done

最初のステートメントを小さくするために、ジョブを別の関数に分割しましたcase。また、ステートメントの$REPLYオプション文字列の代わりに使用しました。オプション文字列caseが短く変更することにしましたが、2つの場所で更新するのを忘れた場合でも壊れないからです。また、スクリプトの後続の呼び出しPS3に影響を与える可能性があるため、触れないようにしました。select別のプロンプトが必要な場合は一度設定してそのままにします(おそらくPS3="Your choice: ")。これにより、複数の問題を含むスクリプトにさらに統一された感じを与えることができます。

ユーザーが操作を完了するまですべてを繰り返す外部ループを追加しました。最初の文の質問を再表示するには、このループが必要ですselect

それ以外の場合は、スクリプトを中断する以外に終了する方法はbreakありcaseません。

aの目的は、select実際にスクリプトのメインイベントループ(それ自体)になるのではなく、ユーザーから質問に対する答えを得ることです。通常、a select- はcase実際に変数を設定するか、関数を呼び出して続行する必要があります。

最初のバージョンに「exit」オプションを含む短いバージョンselect

check_update () {
    echo "Checking update"
}

reinstall_theme () {
    echo "Reinstalling theme"
}

while true; do
    options=("Check for update" "Reinstall theme" "Quit")

    echo "Choose an option: "
    select opt in "${options[@]}"; do
        case $REPLY in
            1) check_update; break ;;
            2) reinstall_theme; break ;;
            3) break 2 ;;
            *) echo "What's that?" >&2
        esac
    done
done

echo "Bye bye!"

答え2

doループは無限であり、select文はその外部にあります。スクリプトはselectステートメントを一度実行してからdoループチェックケース$ optに続けます。私の提案は、ケースの説明の後にブレークを追加することです。

esac
break
done

その後、スクリプト全体を繰り返すには、selectステートメントからdidステートメントまですべてを含む別のループを作成します。

答え3

私はこのトリックを使います:

options=("First option" "Second option" "Quit")
PS3="So what? "
select opt in "${options[@]}"
do
    case $opt in
        "First option")
            echo "First option"
            ;;
        "Second option")
            echo "Second option"    
            ;;
        "Quit")
            echo "We are done..."
            break
            ;;
        *) 
            PS3="" # this hides the prompt
            echo asdf | select foo in "${options[@]}"; do break; done # dummy select 
            PS3="So what? " # this displays the common prompt
            ;;
    esac
done

答え4

私の方法を確認することもできます。単純なループでfunction処理します。for

for((i=0;i<${#opt[@]};i++));do echo "$((i+1))) ${opt[$i]}";done

私のサンプルコードは次のとおりです。

msg="Choose an option:"
opt=("Check_for_update" "Reinstall_theme")

refresh_the_list(){
echo -e "\n$msg"
for((i=0;i<${#opt[@]};i++))
do
        echo "$((i+1))) ${opt[$i]}"
done
}
echo $msg
select i in ${opt[@]}
do
        case $i in
                        ${opt[0]})
                                echo "Checking update"
                                refresh_the_list;;
                        ${opt[1]})
                                echo "Reinstalling"
                                refresh_the_list;;
                        *)
                                echo "invalid option"
                                refresh_the_list;;
        esac
done

関連情報