当没有匹配命令行参数时,getopts打印帮助信息。

4
我将使用getopts在bash中解析命令行参数,但我无法弄清如何实现“默认”操作,如果没有匹配的参数(或未给出命令行参数)。以下是我目前尝试的轻微简化版本:
while getopts v:t:r:s:c: name;
do
        case $name in
        v) VALIDATE=1;;
        t) TEST=1;;
        r) REPORT=1;;
        s) SYNC=1;;
        c) CLEAR=1;;
        *) print_help; exit 2;;
        \?) print_help; exit 2;;
        esac
done

有没有简单的方法让它在输入不匹配时调用print_help; exit 2;?
4个回答

6

根据您的问题和Aditya答案下面的评论,我建议如下:

[getopts]$ cat go
#!/bin/bash

function print_help { echo "Usage" >&2 ; } 

while getopts vtrsc name; do
    case $name in
        v) VALIDATE=1;;
        t) TEST=1;;
        r) REPORT=1;;
        s) SYNC=1;;
        c) CLEAR=1;;
        ?) print_help; exit 2;;
    esac
done

echo "OPTIND: $OPTIND"
echo ${#@}

shift $((OPTIND - 1))

while (( "$#" )); do
    if [[ $1 == -* ]] ; then
        echo "All opts up front, please." >&2 ; print_help ; exit 2
    fi
    echo $1
    shift
done

因为这些都是布尔标志选项,所以您不需要(实际上,也不想要)参数,所以我们去掉了冒号。这些字符都不在 IFS 中,因此我们不需要将其用引号括起来,getopts 会将其视为一个令牌。

接下来,我们将 \? 更改为单个 ? 并删除 *,因为* 将在文字字面量 \? 之前匹配,因此我们可以将规则组合成单个默认匹配。这很好,因为任何使用“-”前缀指定的选项都应该是选项,用户会期望程序在他们指定不期望的选项时失败。

getopts 将解析直到遇到第一个非参数的东西,并将 OPTIND 设置为该位置的值。在本例中,我们将从前面移出 OPTIND - 1(因为 opts 从 0 开始计数)。然后,我们将通过移位从它们中取出这些参数,回显它们或者失败(如果它们以 - 开头)。

测试:

[getopts]$ ./go
OPTIND: 1
0
[getopts]$ ./go -t -v go go
OPTIND: 3
4
go
go
[getopts]$ ./go -d -v go go
./go: illegal option -- d
Usage
[getopts]$ ./go -t go -v go -d
OPTIND: 2
5
go
All opts up front, please.
Usage

4

请尝试以下解决方法:

# Parse the arguments.
while getopts ':h?f:' opts; do
  case ${opts} in

    f) # Foo argument.
      ;;

    # My other arguments.

    \? | h | *) # Prints help.
      grep " .)\ #" $0
      exit 0
      ;;
  esac
done

基本上,-?/-h 会根据其自身源代码打印带有注释的参数。在选项前指定 : 将为任何其他未知参数打印帮助信息。

很好地利用了grep。这样可以节省编写打印帮助函数的时间。不过,我需要将“h\?”添加到参数列表中,以避免出现“非法选项”的输出。 - Wayne Weibel

2

v:t:r:s:c: 应该用双引号括起来

 "v:t:r:s:c:"

根据您发布的脚本,也许您不需要所有那些冒号:。此外,您不需要*)

谢谢,有没有办法匹配“非参数”,例如“./script asdf”? - Tomas Pruzina
我脑海中不知道。你试过用更新的脚本吗? - Aditya Naidu
当getopts返回时,OPTIND被设置为第一个非选项参数的索引。 - David Souther
该字符串不需要加引号,因为它不包含空格。 - glenn jackman

1

如果你想启用?匹配无效选项--:vtrsc,你需要在getopts选项字符串中提供一个前导冒号。另外,在?之前不需要加反斜杠。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接