bash 交互菜单,空输入时退出

bash interactive menu, exit on empty input

我试图拼凑一个脚本来列出不同的 jws 目录,并允许用户在继续编辑目录中的 jnlp 文件之前 select 不同的客户端目录。我的编辑部分在工作,我的菜单主​​要在工作;一旦 selections 完成,我不知道如何退出循环。

我希望它在没有数字 selection 的情况下按 ENTER 后退出,然后继续脚本的下一部分。

function update_jnlp
{
 while :
  do
 # JNLP update submenu

options=($(ls /tmp/test/ | grep "jws$"))

menu() {
    clear
    echo "Locally installed jnlps:"
    for i in ${!options[@]}; do
       printf "%3d%s) %s\n" $((i+1)) "${choices[i]:- }" "${options[i]}"
    done
    [[ "$msg" ]] && echo "$msg"; :
     }

prompt="Check an option (again to uncheck, ENTER when done): "
    while menu && read -rp "$prompt" num && [[ "$num" ]]; do
       [[ "$num" != *[![:digit:]]* ]] &&
       (( num > 0 && num <= ${#options[@]} )) ||
       { msg="Invalid option: $num"; continue; }
       ((num--)); msg="${options[num]} was ${choices[num]:+un}checked"
       [[ "${choices[num]}" ]] && choices[num]="" || choices[num]="+"
    done
printf "You selected"; msg=" nothing"
    for i in ${!options[@]}; do
       [[ "${choices[i]}" ]] && { printf " %s" "${options[i]}"; msg=""; }
    done
    done
    for i in ${choices[@]}; do
            printf "%s\n" ${choices[@]};
    echo "fun"
        done
        echo "@msg"
# here is the script to edit the files now contained as ${choices[@]}
 }

我发现我处于菜单循环中,我需要验证来自读取命令的输入 = "" 或 $prompt 输入是否为空,我假设我从那里中断

请将您的代码格式化为更具可读性。就目前而言,不稳定的缩进使它几乎不可读。好吧,缩进与在另一个函数内的循环体中定义一个函数以及我见过的一些更难以理解的循环体相结合。 (我以为我已经看到了很多;显然,我还有一些学习要做。)

随着代码格式的更正统,你有:

function update_jnlp
{
    while :
    do
        # JNLP update submenu
        options=($(ls /tmp/test/ | grep "jws$"))

        menu() {
            clear
            echo "Locally installed jnlps:"
            for i in ${!options[@]}; do
               printf "%3d%s) %s\n" $((i+1)) "${choices[i]:- }" "${options[i]}"
            done
            [[ "$msg" ]] && echo "$msg"; :
        }

        prompt="Check an option (again to uncheck, ENTER when done): "
        while menu && read -rp "$prompt" num && [[ "$num" ]]; do
            [[ "$num" != *[![:digit:]]* ]] &&
            (( num > 0 && num <= ${#options[@]} )) ||
            { msg="Invalid option: $num"; continue; }
            ((num--)); msg="${options[num]} was ${choices[num]:+un}checked"
            [[ "${choices[num]}" ]] && choices[num]="" || choices[num]="+"
        done

        printf "You selected"; msg=" nothing"
        for i in ${!options[@]}; do
            [[ "${choices[i]}" ]] && { printf " %s" "${options[i]}"; msg=""; }
        done

        echo "$msg"    # Added
        break          # Added

    done

    for i in ${choices[@]}; do
        printf "%s\n" ${choices[@]};
        echo "fun"
    done
    echo "@msg"
    # here is the script to edit the files now contained as ${choices[@]}
}

当我运行时,我选择了1、3、7,然后点击return,最后一页输出如下:

Locally installed jnlps:
  1+) abc.jws
  2 ) def.jws
  3+) ghi.jws
  4 ) jkl.jws
  5 ) mno.jws
  6 ) pqr.jws
  7+) stu.jws
  8 ) vwx.jws
  9 ) xyz.jws
stu.jws was checked
Check an option (again to uncheck, ENTER when done): 
You selected abc.jws ghi.jws stu.jws
+
+
+
fun
+
+
+
fun
+
+
+
fun
@msg

如果不添加 break,您将看不到选择的内容,因为外层 while : 循环清除屏幕的速度太快。添加 echo "$msg" 后,您将得到 You selected nothing,如您所愿。

while :循环之后的material显然没有完成。

事实上,您根本不需要 while : 循环,或者不完整的 material。您可以使用:

function update_jnlp
{
    # JNLP update submenu
    options=($(ls /tmp/test/ | grep "jws$"))

    menu() {
        clear
        echo "Locally installed jnlps:"
        for i in ${!options[@]}; do
           printf "%3d%s) %s\n" $((i+1)) "${choices[i]:- }" "${options[i]}"
        done
        [[ "$msg" ]] && echo "$msg"; :
    }

    prompt="Check an option (again to uncheck, ENTER when done): "
    while menu && read -rp "$prompt" num && [[ -n "$num" ]]; do
        [[ "$num" != *[![:digit:]]* ]] &&
        (( num > 0 && num <= ${#options[@]} )) ||
        { msg="Invalid option: $num"; continue; }
        ((num--)); msg="${options[num]} was ${choices[num]:+un}checked"
        [[ "${choices[num]}" ]] && choices[num]="" || choices[num]="+"
    done

    printf "You selected"; msg=" nothing"
    for i in ${!options[@]}; do
        [[ "${choices[i]}" ]] && { printf " %s" "${options[i]}"; msg=""; }
    done
    echo "$msg"

}

这仍然相当难以理解,但至少它或多或少是正常工作的。