代码之家  ›  专栏  ›  技术社区  ›  Mike Slinn

Bash咒语,用于以编程方式定义whiptail放射科医生

  •  0
  • Mike Slinn  · 技术社区  · 7 年前

    我要发出类似于以下命令的bash命令:

    whiptail --title 'Select Database' --radiolist 'Select Database:' 10 80 2 \
      1 production off \
      2 localhost  on
    

    Whiptail对于如何指定单选列表值非常特别。如图所示,必须在各自的生产线上提供。 Here is a good article on this question .

    数据库列表在名为 DBS ACTIVE_DB 是要在whiptail对话框中突出显示的放射列表项。

    DBS="production localhost"
    ACTIVE_DB="localhost"
    DB_COUNT="$( echo "$DBS" | wc -w )"
    
    DB_LIST="$(
      I=1
      echo ""
      for DB in $DBS; do
        SELECTED="$( if [ "$DB" == "$ACTIVE_DB" ]; then echo " on"; else echo " off"; fi )"
        SLASH="$( if (( $I < $DB_COUNT )); then echo \\; fi )"
        echo "  $I $DB $SELECTED $SLASH"
        echo ""
        I=$(( I + 1 ))
      done
    )"
    
    OPERATION="whiptail \
      --title \"Select Database\" \
      --radiolist \
      \"Select Database:\" \
      10 80 $DB_COUNT \"${DB_LIST[@]}\""
    
    eval "${OPERATION}"
    

    set -xv 
    ++ whiptail --title 'Select Database' --radiolist 'Select Database:' 10 80 2 '
      1 production  off
      2 localhost  on '
    

    解决方案需要提供一种方法,以某种方式知道用户做出了哪些选择,或者他们是否按了ESC键。ESC通常将返回代码设置为255,所以这应该不难,但是当尝试检索用户选择的放射虫项目的值时,这个问题变得非常混乱。

    2 回复  |  直到 7 年前
        1
  •  4
  •   Charles Duffy    7 年前

    以下是中列出的最佳实践 BashFAQ #50 :

    # note that lower-case variable names are reserved for application use by POSIX
    # see https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
    active_db="localhost"
    dbs=( production localhost ) # using an array, not a string, means ${#dbs[@]} counts
    
    # initialize an array with our explicit arguments
    whiptail_args=(
      --title "Select Database"
      --radiolist "Select Database:"
      10 80 "${#dbs[@]}"  # note the use of ${#arrayname[@]} to get count of entries
    )
    
    i=0
    for db in "${dbs[@]}"; do
      whiptail_args+=( "$((++i))" "$db" )
      if [[ $db = "$active_db" ]]; then    # only RHS needs quoting in [[ ]]
        whiptail_args+=( "on" )
      else
        whiptail_args+=( "off" )
      fi
    done
    
    # collect both stdout and exit status
    # to grok the file descriptor switch, see https://stackoverflow.com/a/1970254/14122
    whiptail_out=$(whiptail "${whiptail_args[@]}" 3>&1 1>&2 2>&3); whiptail_retval=$?
    
    # display what we collected
    declare -p whiptail_out whiptail_retval
    

    而我却没有 whiptail 方便测试,上面代码运行的确切调用与以下完全相同:

    whiptail --title "Select Database" \
             --radiolist "Select Database:" 10 80 2 \
              1 production off \
              2 localhost on 
    

    eval ed,运行可以生成精确命令的命令:

    printf '%q ' whiptail "${whiptail_args[@]}"; echo
    
        2
  •  1
  •   John Kugelman Michael Hodel    7 年前

    使用数组。他们会让这容易十倍。我们从小事做起,努力向上。这是 $DBS $DB_COUNT 以数组形式:

    DBS=(production localhost)
    DB_COUNT=${#DBS[@]}
    

    这里的优势是 $DBS公司 实际上有两个条目,所以我们可以用 ${#DBS[@]} 不需要向外部命令(如 wc .

    $DB_LIST . 您尝试在每个循环迭代中添加几个选项。让我们将其转换为数组语法,使用 array+=(foo bar baz) 附加项目。

    DB_LIST=()
    I=1
    for DB in "${DBS[@]}"; do
      if [ "$DB" == "$ACTIVE_DB" ]; then SELECTED=on; else SELECTED=off; fi
      DB_LIST+=("$I" "$DB" "$SELECTED")
      I=$(( I + 1 ))
    done
    

    $SLASH 变量。换行不重要,再见 echo ""

    最后,让我们运行whiptail。不需要所有疯狂的引用 eval -再也没有了。我们可以直接运行它并在正确的位置扩展我们构建的数组。

    whiptail --title "Select Database" --radiolist "Select Database:" 10 80 "$DB_COUNT" "${DB_LIST[@]}"
    

    推荐文章