【问题标题】:Create an interactive Shell prompt menu from a dynamic list?从动态列表创建交互式 Shell 提示菜单?
【发布时间】:2022-01-09 13:50:24
【问题描述】:

以下提示应允许用户根据输出到数组的填充列表进行选择,然后打印列表及其索引,并要求用户从列表中选择一个数字,然后将其设置为多变的。只允许一个选项,如果用户指定的选项不正确,脚本会提示选择正确的数字。

Multiple devices detected, please select one from the list:
1. Device1
2. Device2
3. Device3

1
You have selected device Device1

下面的代码不起作用并且有很多语法错误,首先我想让脚本检测arr=($(ip ad|awk '/state UP/ {print $2}'))的输出是否包含多个条目,如果是则运行脚本,否则设置一个默认值。 case 语句不是动态的,但是如果超过 2 个类似下面的 case 就会失败,也许是一个循环?

host_interfaces()
{
   arr=($(ip ad|awk '/state UP/ {print $2}'))
   echo "Multiple devices detected, please select one from the list:"
   for i in "${!arr[@]}"; do
   printf "%s%s\n" "$i.  " "${arr[$i]}"
   done
   PS3='Please enter your choice: '
   select opt in "${arr[@]}"
   do
      case $opt in
            "$opt")
               echo "You have selected device $opt"
               export HOST_INTERFACE=$opt
               ;;
            *) echo "invalid option
               break
               ;;
      esac
   done
}

【问题讨论】:

  • ${#arr[@]} 扩展为数组中的条目数。所以[ "${#arr[@]}" -eq 1 ]也许是你正在寻找的测试。
  • 我不确定我是否了解所有细节。当你的用户选择一个有效的选项时,你想做什么?继续要求选择还是停在那里? Same question when the choice is not valid or when the choice corresponds to Quit.
  • 试试dialog/whiptail
  • @RenaudPacalet 当用户选择一个有效选项时,该值设置为 HOST_INTERFACE 并且函数结束。我删除了“退出”,因为它是示例代码 sn-p 的一部分,因此唯一的选项是数组中的有效选择或无效选择。
  • @Kev 好的,我相应地更新了我的答案。请编辑您的问题并修改它以反映您的真实规格(SO 对其他有类似问题的访问者也很有用,因此问题非常清晰和准确很重要)。

标签: linux bash loops shell scripting


【解决方案1】:

这个,也许吧?

host_interfaces()
{
  local opt='' h=''
  arr=($(ip ad|awk '/state UP/ {print $2}'))
  if [ "${#arr[@]}" -eq 1 ]; then
    echo "One single device detected"
    h="${arr[0]}"
  elif [ "${#arr[@]}" -gt 1 ]; then
    echo "Multiple devices detected, please select one from the list:"
    PS3='Please enter your choice: '
    select opt in "${arr[@]}"
    do
      case "$opt" in
        "")
          echo "Invalid choice"
          h=''
          ;;
        *)
          echo "You have selected device $opt"
          h="$opt"
          break
          ;;
      esac
    done
  else
    echo "No device detected"
  fi
  echo "Selected device: ${h:-none}"
  export HOST_INTERFACE="$h"
  [ -z "$h" ] && return 1 || return 0
}

请注意,如果未找到或选择有效设备,则该函数返回 1,否则返回 0。因此您可以将其用于:

if host_interfaces; then
  echo "HOST_INTERFACE = $HOST_INTERFACE"
else
  echo "No device selected"
fi

【讨论】:

  • 为什么使用本地?是不是这样你就可以简单地创建一个范围内的局部变量,因为它的值被导出到 HOST_INTERFACE,所以它在函数范围之外没有用处?并且可以释放内存,从而使脚本更高效?
  • ${h:-none}"":-none"的目的是什么?
  • local 的作用与许多编程语言中的作用相同:限制范围。局部变量在其范围之外没有可见性,这是​​良好的编程习惯。如果 h 未设置或为 null,则 ${h:-none} 扩展为 none。注意:所有这些都在 bash 手册中有很好的记录。如果您正在学习 bash 编程,我强烈建议您开始使用手册 (man bash) 作为主要参考。它写得很好,组织得很好,可搜索......如果你搜索:-,你的第一个命中就是正确的。
  • 谢谢!将把它作为未来的参考点。
【解决方案2】:

解决方案:

#! /bin/bash

declare HOST_INTERFACE=

function host_interfaces() {
    local -a arr=($(ip ad | awk '/state UP/ {gsub(/:/, "", $2); print $2}'))
    if [ "${#arr[@]}" -eq 1 ]; then
        HOST_INTERFACE="${arr[0]}"
        return 0
    fi
    local opt=
    HOST_INTERFACE=
    echo "Multiple devices detected, please select one from the list:"
    PS3='Please enter your choice: '
    # Add "Quit" value to the items
    select opt in "${arr[@]}" Quit; do
        # "opt" does not contains the number but the associated value
        case $opt in
            "Quit")
                # 
                break
            ;;
            "")
                # No value found
                echo "invalid option"
            ;;
            *)
                echo "You have selected device $opt"
                export HOST_INTERFACE=$opt
                break
            ;;
        esac
    done
}

host_interfaces

【讨论】:

    【解决方案3】:

    这里可以简单地使用dialog

    dialog --backtitle "Device selection" --title "Multiple devices detected" --menu "please select one from the list:" 10 45 4 1 "Device1" 2 "Device2" 3 "Device3"
    

    man dialog

    【讨论】:

    • 谢谢@NVRM,但我在命令行上寻找解决方案,因为这将是更大脚本的一部分,编辑问题以便更清楚。
    猜你喜欢
    • 2018-12-28
    • 1970-01-01
    • 2011-12-21
    • 1970-01-01
    • 2013-01-11
    • 2021-11-28
    • 2013-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多