陷阱getopt无效选项

时间:2011-10-05 15:06:58

标签: bash shell case getopt

我正在使用getopt(而非getops)为我的bash脚本提供处理选项和切换(long -option和short -o表单)的能力。

我希望能够捕获无效选项并处理它们,通常会回应用户应该尝试cmd --help然后退出脚本。

事实是,getopt捕获了无效选项,它本身输出了一条消息,例如“getopt:invalid option - 'x'”

这是我用来设置我的getopt参数的模式:

set -- $(getopt -o $SHORT_OPTIONS -l $LONG_OPTIONS -- "$@")

其中$ LONG_OPTIONS和$ SHORT_OPTIONS都是以逗号分隔的选项列表。

以下是处理选项的方法:

 while [ $# -gt 0 ]
    do
        case "$1" in
            -h|--help)
                cat <<END_HELP_OUTPUT

    Help
    ----

    Usage: ./cmd.sh 

    END_HELP_OUTPUT

                shift;
                exit
                ;;
            --opt1)
                FLAG1=true
                shift
                ;;
            --opt2)
                FLAG2=true
                shift
                ;;
            --)
                shift
                break
                ;;
            *)
                echo "Option $1 is not a valid option."
                echo "Try './cmd.sh --help for more information."
                shift
                exit
                ;;
        esac
    done

getopt -q会抑制输出,但case语句中的陷阱方案仍然无法达到预期效果。相反,尽管参数无效,程序才会执行。

6 个答案:

答案 0 :(得分:9)

This这种风格对我有用:

params="$(getopt -o d:h -l diff:,help --name "$cmdname" -- "$@")"

if [ $? -ne 0 ]
then
    usage
fi

eval set -- "$params"
unset params

while true
do
    case $1 in
        -d|--diff)
            diff_exec=(${2-})
            shift 2
            ;;
        -h|--help)
            usage
            exit
            ;;
        --)
            shift
            break
            ;;
        *)
            usage
            ;;
    esac
done

答案 1 :(得分:1)

这不是最强大的解决方案,但它是合理的;它依赖于以下内容:

  • getopt打印的错误消息前缀为“getopt:”
  • 假设可以通过清除版本的getopt错误消息,并使用自定义信息进行扩充。

代码段:

# Invoke getopt; suppress its stderr initially.
args=$(getopt -o $SHORT_OPTIONS -l $LONG_OPTIONS -- "$@" 2>/dev/null)
if [[ $? -ne 0 ]]; then # getopt reported failure
    # Rerun the same getopt command so we can capture stderr output *only* this time.
    # Inefficient (and a potential maintenance headache, if literals were involved), but this will only execute in case of invalid input.
    # Alternatively, redirect the first getopt invocation's stderr output to a temp. file and read it here.
    errmsg=$(getopt -o $SHORT_OPTIONS -l $LONG_OPTIONS -- "$@" 2>&1 1>&-)
    # Strip getopt's prefix and augment with custom information.
    echo -e "${errmsg#getopt: }\nTry './cmd.sh --help for more information." 1>&2
    exit 1
fi

答案 2 :(得分:1)

你必须使用getopt吗?如果您只是使用

while [ $# -gt 0 ]; do
  case "$1" in
    -d|--diff)
       diff_exec=(${2-})
       shift
       ;;
    -h|--help)
       usage
       exit
       ;;
     --)
       break
       ;;
     *)
       usage
       ;;
    esac
    shift
done

然后你自己的代码正在进行检查。

答案 3 :(得分:1)

我发现这可以作为getopts案例陈述中的最后一项:

*)eval echo“无法识别的arg \ $$ [OPTIND-1]”;用法;退出;;

答案 4 :(得分:0)

我不确定这是否有帮助,但 getopt(1)使用 getopt(3)并且如果我没记错的话 getopt(3)< / em>如果 OPTSTRING 的第一个字符是冒号,则抑制错误报告。

答案 5 :(得分:0)

这是我使用过的命令行解析。它可以通过更多的解析逻辑来改进,以处理丢失的选项和参数。

对于命令行:-a AA -b BB -c CC,结果s / b a = AA b = BB c = CC

OPT=( "$@" )  # Parses the command line into words.

for [[ I=0;I<${#OPT[@]};I++ ]]  
   do
      case "${OPT[$I]}" in         
         -a) a=${OPT[$I+1]} ;;         
         -b) b=${OPT[$I+1]} ;;         
         -c) c=${OPT[$I+1]} ;;    
      esac
  done