如何检测到getopts没有传递任何选项?


19

我有此代码-

#getoptDemo.sh
usage()
{
    echo "usage: <command> options:<w|l|h>"
}
while getopts wlh: option
do
    case $option in
            (w)
                    name='1';;
            (l)
                    name='2';;
            (h)
                    name='3';;
            (*)
                    usage
                    exit;;
    esac
done
print 'hi'$name

当我运行时bash getoptDemos.sh(不带选项),它将打印hi而不是调用函数usage。当给出w,h和l以外的选项时,它将调用用法。然后,如果未指定任何选项,它将无法正常工作。

我已经尝试使用?\?:到位的*,但我无法实现我想要的。我的意思是所有的docsgetopt说它使用?

我究竟做错了什么?


您在什么外壳下运行它?
朱利安

我正在运行它/bin/bash
侯赛因·坦波利

Answers:


15

在不带任何选项的情况下运行此脚本时,getopt将返回false,因此它根本不会进入循环。它只会显示在打印纸上-这是ksh / zsh吗?

如果必须选择一个选项,则最好在循环后测试$ name。

if [ -z "$name" ]
then
   usage
   exit
fi

但是请确保$name在调用之前为空getopts(因为$name在启动时shell接收到的环境中可能有一个)

unset name

(在getopts循环之前)


没有。它的重击。那么我如何实现我想要的- no argument使用bash 处理条件。
侯赛因·坦波利

如果您想要一个强制性选项,我认为这是不可能的-这可能就是为什么它们被称为选项的原因:)不过,您可以在循环后测试$ name以确保已设置它。如果[-z“ $ name”]; 然后使用;出口 ; fi
朱利安(Julian)

谢谢。上面的代码确实有帮助。可惜的getopts是没有这样的规定。糟糕的是,这不能阻止你。
侯赛因·坦波利(Russain Tamboli),2012年

如果我正在运行其他Shell怎么办?zsh,sh。bash以外的其他shell可以解决这种情况吗?
侯赛因·坦波利

20

getopts依次处理选项。那是它的工作。如果用户碰巧不传递任何选项,则第一次调用将getopts退出while循环。

如果所有选项都不带参数,则值OPTIND指示传递了多少个选项。通常,OPTIND与非选项参数(操作数)相对应的是作为选项或选项参数的参数数量。

while getopts …; do …; done
if [ $OPTIND -eq 1 ]; then echo "No options were passed"; fi
shift $((OPTIND-1))
echo "$# non-option arguments"

无论如何,您不是要确定是否没有选项,而是要确定name-setting选项是否没有传递。因此,请检查是否name未设置(并注意先将其取消设置)


1
谢谢。为您+1。当我将代码中的最后3行放入sample.sh并运行时bash sample.sh -abc file.txt,结果为- 1 non-option arguments。我如何找出给出了多少个选项。(此处3)
侯赛因·坦波利

1
奇怪的是,没有人对此轻微错误发表评论-如果没有给出任何选项,则在“ while getopts ...”循环之后,OPTIND将为1。因此,if检查应检查是否等于1,而不是零。
丹尼尔(Daniel)

4

如果您的脚本在任何情况下都必须接收选项参数,请将此块放在开头(在getops之前)。

if [[ ! $@ =~ ^\-.+ ]]
then
  #display_help;
fi

块检查参数字符串不是以-符号开头,这表明第一个参数不是选项参数。


2

我会用一个变量检查​​它。如果在没有参数的情况下getopts从不通过循环,则可以使用如下示例:

#getoptDemo.sh
usage()
{
    echo "usage: <command> options:<w|l|h>"
}

no_args="true"
while getopts wlh: option
do
    case $option in
            (w)
                    name='1';;
            (l)
                    name='2';;
            (h)
                    name='3';;
            (*)
                    usage
                    exit;;
    esac
    no_args="false"
done

[[ "$no_args" == "true" ]] && { usage; exit 1; }

print 'hi'$name

0

在您的代码getopts块之前,请检查$1(在命令行中传递的第一个参数/选项)是否等于空字符串。如果是,请打印使用情况消息并退出,(或者,如果您是无政府主义者,则执行一些“无选项”功能),否则让我们getopts像正常情况一样解析这些选项。

此功能未包含在getopts中的原因是因为您已经可以使用“ if-else”在bash中完成该功能。例:

if [[ $1 == "" ]]; then
    Your_Usage_Function;
    exit;
else
   #parse options with getopts code block here;
fi

合理?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.