【问题标题】:getopts won't call twice in a row? [duplicate]getopts 不会连续调用两次? [复制]
【发布时间】:2011-06-30 05:14:30
【问题描述】:

由于某种原因,选项在第一次调用 lib_progress_bar -c "@" -u "_" 0 100 时工作正常,但在第二次调用时,一切都是默认的,因为第二次似乎 getopts c:u:d:p:s:%:m: flag 不是真的,或者至少这种情况永远不会当我使用set -x时执行

#!/bin/bash



lib_progress_bar() {
    local current=0
    local max=100 
    local completed_char="#"    
    local uncompleted_char="."  
    local decimal=1 
    local prefix=" ["
    local suffix="]"
    local percent_sign="%"
    local max_width=$(tput cols)

    local complete remain subtraction width atleast percent chars
    local padding=3

    while getopts c:u:d:p:s:%:m: flag; do
        case "$flag" in
            c) completed_char="$OPTARG";;
            u) uncompleted_char="$OPTARG";;
            d) decimal="$OPTARG";;
            p) prefix="$OPTARG";;
            s) suffix="$OPTARG";;
            %) percent_sign="$OPTARG";;
            m) max_width="$OPTARG";;
        esac
    done
    shift $((OPTIND-1))


    current=${1:-$current} 
    max=${2:-$max} 


    if (( decimal > 0 )); then
        (( padding = padding + decimal + 1 ))
    fi


    let subtraction=${#completed_char}+${#prefix}+${#suffix}+padding+${#percent_sign}
    let width=max_width-subtraction


    if (( width < 5 )); then
        (( atleast = 5 + subtraction ))
        echo >&2 "the max_width of ($max_width) is too small, must be atleast $atleast" 
        return 1 
    fi


    if (( current > max ));then
        echo >&2 "current value must be smaller than max. value"
        return 1
    fi

    percent=$(awk -v "f=%${padding}.${decimal}f" -v "c=$current" -v "m=$max" 'BEGIN{printf('f', c / m * 100)}')

    (( chars = current * width / max))

    # sprintf n zeros into the var named as the arg to -v
    printf -v complete '%0*.*d' '' "$chars" ''
    printf -v remain '%0*.*d' '' "$((width - chars))" ''

    # replace the zeros with the desired char
    complete=${complete//0/"$completed_char"}
    remain=${remain//0/"$uncompleted_char"}

    printf '%s%s%s%s %s%s\r' "$prefix" "$complete" "$remain" "$suffix" "$percent" "$percent_sign"

    if (( current >= max )); then
        echo ""
    fi
}


lib_progress_bar -c "@" -u "_" 0 100 
echo
lib_progress_bar -c "@" -u "_" 25 100
echo
lib_progress_bar -c "@" -u "_" 50 100
echo

exit;

【问题讨论】:

    标签: bash shell getopts


    【解决方案1】:

    要解释丹尼斯的答案为何有效,请参阅 bash 手册页(搜索 getopts):

    每次调用 shell 或 shell 脚本时,都会将 OPTIND 初始化为 1。

    shell 不会自动重置 OPTIND;如果要使用一组新参数,则必须在同一 shell 调用中多次调用 getopts 之间手动重置它。

    这就是getopts 处理多个选项的方式。

    如果getopts 没有在OPTIND 变量中维护全局状态,则在while 循环中每次调用getopts 都会继续处理$1,并且永远不会前进到下一个参数。

    【讨论】:

      【解决方案2】:

      只需添加:

      local OPTIND
      

      在函数的顶部。

      【讨论】:

      • 我在 getopts-while-loop 和 shift 之后使用 OPTIND=0。我不知道local OPTIND 技巧,但是如果您在相同的函数 中多次奇怪地调用getopts,则归零应该可以工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多