在Bash中测试命令行参数

22

我正在测试我的脚本的第一个参数是否为--foo

if [ $# > 1 ]
then
    if [[ "$1" = "--foo" ]]
    then
        echo "foo is set"
        foo = 1
    fi
fi

if [[ -n "$foo"]]
then
    #dosomething
fi

请问有没有用bash的方法来测试参数列表中是否包含--foo,不一定在第一个位置?


1
@Prospero:链接失效了。 - realtebo
2个回答

35
如果您想要支持长选项,应使用外部getopt工具。如果只需要支持短选项,则最好使用Bash内置的getopts

以下是使用getopts的示例(getopt也不太不同):

options=':q:nd:h'
while getopts $options option
do
    case $option in
        q  )    queue=$OPTARG;;
        n  )    execute=$FALSE; ret=$DRYRUN;; # do dry run
        d  )    setdate=$OPTARG; echo "Not yet implemented.";;
        h  )    error $EXIT $DRYRUN;;
        \? )    if (( (err & ERROPTS) != ERROPTS ))
                then
                    error $NOEXIT $ERROPTS "Unknown option."
                fi;;
        *  )    error $NOEXIT $ERROARG "Missing option argument.";;
    esac
done

shift $(($OPTIND - 1))

不要以为你的第一个测试总是会显示 true 并在当前目录下创建名为 "1" 的文件。建议使用以下方式(按优先级排序):

if (( $# > 1 ))
或者
if [[ $# -gt 1 ]]
或者
if [ $# -gt 1 ]

此外,在赋值语句中,等号周围不能有空格:

foo=1

谢谢,我改用getopts了。我发现通过随意搜索谷歌无法学好bash,有很多陷阱,必须更加系统化 :) - MK.
@MK:在SO上有很多关于Bash的好问题和答案,还有一些包括指向更多学习资源的指针。 - Dennis Williamson

12

正如Dennis所指出的那样,getoptgetopts是解析命令行参数的标准方式。如果想要另一种替代方式,可以使用特殊变量$@,它会扩展成所有的命令行参数。因此,你可以在测试中使用通配符来测试它:

#!/usr/bin/env bash

if [[ $@ == *foo* ]]
then
    echo "You found foo"
fi

话虽如此,但你最好尽早学会getopt。


4
无需双倍使用星号。这种技术可以作为快速测试,但容易产生假阳性结果。 - Dennis Williamson
1
没错 - 很容易出现误报。我总是记不住双星号在哪里使用;我的记忆在这里失败了。感谢您的纠正! - Peter Wagener
1
关于双星号,我想到的唯一事情是在Bash 4中使用shopt -s globstar、zsh和ksh93进行递归式全局匹配。 - Dennis Williamson
我认为你应该编辑你的答案,去掉双星号。这种方法非常方便,可以为你的脚本添加--help或--version。[[ $@ == <asterisk>--help<asterisk> ]] - lafferc

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