使用bash getopts命令处理多个必需选项

54

能否使用getopts一次处理多个选项?例如,myscript -iR或myscript -irv。

此外,当脚本满足某些条件时,需要强制使用一个选项。例如,如果脚本参数是目录,则需要指定-R或-r选项以及任何其他选项(myscript -iR mydir或myscript -ir mydir或myscript -i -r mydir或myscript -i -R mydir)。如果是文件则仅需要-i选项(myscript -i myfile)。

我尝试过搜索,但没有找到答案。

1个回答

130

您可以连接提供的选项,getopts将对它们进行分离。在您的case语句中,您将单独处理每个选项。

当看到选项时,您可以设置一个标志,并检查以确保在getopts循环完成后存在必需的“选项”(!)。

以下是一个示例:

#!/bin/bash
rflag=false
small_r=false
big_r=false
    
usage () { echo "How to use"; }
    
options=':ij:rRvhm'
while getopts $options option
do
    case "$option" in
        i  ) i_func;;
        j  ) j_arg=$OPTARG;;
        r  ) rflag=true; small_r=true;;
        R  ) rflag=true; big_r=true;;
        v  ) v_func; other_func;;
        h  ) usage; exit;;
        \? ) echo "Unknown option: -$OPTARG" >&2; exit 1;;
        :  ) echo "Missing option argument for -$OPTARG" >&2; exit 1;;
        *  ) echo "Unimplemented option: -$option" >&2; exit 1;;
    esac
done

if ((OPTIND == 1))
then
    echo "No options specified"
fi

shift $((OPTIND - 1))

if (($# == 0))
then
    echo "No positional arguments specified"
fi
    
if ! $rflag && [[ -d $1 ]]
then
    echo "-r or -R must be included when a directory is specified" >&2
    exit 1
fi

这是一个完整的getopts函数的参考实现,但仅是更大脚本的简要概述。


1
非常感谢你,Dennis。我按照你的建议使用了标志(flags)。我尝试通过将选项连接起来并将它们存储在一个变量中来简化逻辑,并在稍后根据所提供的选项进行处理。 - Ramesh Samane
1
未实现选项和未知选项的区别在于前者提供了一个与$options中的选项字符匹配但在case语句中没有条目的选项,而后者提供了一个不与$options中任何字符匹配的选项。 - Dennis Williamson
4
请注意,在算术代码块中,您不需要使用 $ 前缀来表示变量名;因此,您可以直接使用 shift $((OPTIND-1)) - kbolino
4
顺便提一下,* ) echo "Unimplemented option: -$OPTARG" >&2; exit 1;; 应该写成 -$option 而不是 -$OPTARG,否则它会说未实现选项的 参数 而不是未实现选项的 _标志_。使用 -$OPTARG 的原始方式: ./foo.bash -m foo Unimplemented option: -foo如果使用 -$option 您将得到期望的结果: ./foo -m foo Unimplemented option: -m - Elven Spellmaker
1
@ElvenSpellmaker:抱歉,你是正确的。我已经编辑了我的答案。 - Dennis Williamson
显示剩余3条评论

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