函数中调用的 getopts 未拾取标志

abe*_*ger 3 bash getopts

我有从我的调用以下脚本.bash_profile

# Set directories based on current path
__set_dirs() {
    currdir=`pwd`
    if [[ ${currdir} =~ "\/path\/to\/main\/(.*)\/working\/([a-z]+)(/?.*)" ]]
    then
        ws=${BASH_REMATCH[1]}
        subdirs=${BASH_REMATCH[3]}
        stgdir=${ts}/${ws}/STAGING${subdirs}
    else
        echo "${currdir} is not a workspace"
        stgdir=""
    fi
}

# Update local version with staging version
upd() {
    __set_dirs
    if [[ -n ${stgdir} ]]
    then
        __overwrite=0
        while getopts "o" opt
        do
            case $opt in
                o)
                    __overwrite=1
                    ;;
                \?)
                    echo "Invalid option: -$OPTARG" >&2
                    ;;
            esac
        done

        echo "Updating ${currdir} with latest from ${stgdir}..."
        if [ ${__overwrite} -eq 0 ]
        then
            update -r ${stgdir} ${currdir}
        else
            echo "Overwriting all local changes!"
            update -r -w ${stgdir} ${currdir}
        fi
    fi
    unset __overwrite
}
Run Code Online (Sandbox Code Playgroud)

当我执行时

> upd -o
Run Code Online (Sandbox Code Playgroud)

该标志被完全忽略——我从未看到消息“覆盖所有本地更改!”。我是不是错过了什么地方?

更新:确实有效,但仅在我第一次运行脚本时有效。从第二次开始,该标志将被忽略。

abe*_*ger 5

好吧,弄清楚了:

在浏览了的手册页getopts后,我发现了这个花絮(强调我的):

每次调用时,getopts 都会将...下一个要处理的参数的索引放入变量 OPTIND 中。每次调用 shell 或 shell 脚本时,OPTIND 都会初始化为 1... shell 不会自动重置 OPTIND;如果要使用一组新参数,则必须在同一 shell 调用中多次调用 getopts 之间手动重置它。

由于我只通过 .bashrc 运行一次脚本,因此OPTIND只初始化一次。我第一次运行该函数时,一切都很顺利。第二次,OPTIND设置为 2,但getopts没有找到任何内容,因此继续前进。

有了这些知识,我修改upd()为重置OPTIND为 1:

upd() {
    __set_dirs
    if [[ -n ${stgdir} ]]
    then
         __overwrite=0
         OPTIND=1
         while getopts "o" opt
...
Run Code Online (Sandbox Code Playgroud)

这解决了它。OPTIND: 比你想象的更重要。