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

Hus*_*oli 21 shell bash options getopts

我有这个代码 -

#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
Run Code Online (Sandbox Code Playgroud)

当我运行bash getoptDemos.sh(不带选项)时,它会打印hi而不是调用函数usage。当给出 w、h 和 l 以外的选项时,它调用用法。那么当没有指定选项时它就不能工作。

我曾尝试使用?, \?,:代替,*但我无法实现我想要的。我的意思是所有的docsgetopt说它使用?

我究竟做错了什么?

Gil*_*il' 25

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"
Run Code Online (Sandbox Code Playgroud)

在任何情况下,您都不是要确定是否没有选项,而是要确定是否没有name通过 -setting 选项。因此,请检查是否name未设置(并注意先将其取消设置)


Jul*_*ian 21

当您在没有任何选项的情况下运行此脚本时,getopt 将返回 false,因此它根本不会进入循环。它只会下降到打印 - 这是 ksh/zsh 吗?

如果你必须有一个选项,你最好的办法是在循环后测试 $name 。

if [ -z "$name" ]
then
   usage
   exit
fi
Run Code Online (Sandbox Code Playgroud)

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

unset name
Run Code Online (Sandbox Code Playgroud)

getopts循环前)


小智 7

我会用一个变量来检查它。如果 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
Run Code Online (Sandbox Code Playgroud)