3

我有以下从我的调用中调用的脚本.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
}

当我执行

> upd -o

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

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

4

2 回答 2

4

好吧,想通了:

在翻阅手册页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
...

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

于 2013-09-09T21:18:32.250 回答
2

getopts作用于传递给你的函数的参数,所以在你的情况下,你必须用 , 调用upd()函数"$@",以将所有命令行参数传递给你的函数。

例如:

test() {
  while getopts "o" opt; do
    case $opt in
    o)
      echo o
    ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
    ;;
    esac
  done
}
test # this wont work as $1, $2, ... are not set
test $@ # this will work as you pass along the command line parameters

编辑

如果我将上面的示例源到我正在运行的 shell 中,我忽略了这一.bashrc部分,然后test -o按预期工作。

于 2013-09-09T19:31:18.587 回答