6

私は、1 つのオプションのパラメーター ( -t ) の後にいくつかの追加の引数が続く単純な bash スクリプトを作成しています。

getopts はこれを達成するための合理的な方法だと思っていましたが、目的の動作を得るのに苦労しています。私が持っているものは次のとおりです。

foo() {
    baz=10
    while getopts ":t:" option; do
        case "$option" in
        t) baz=$OPTARG ;;
        esac
    done
    shift $((OPTIND - 1))
    bar -t $baz $1 $2 $3
}

問題は$OPTIND、引数が存在するかどうかによって変化しないように見えるため、オプションのパラメーターで期待どおりの正しい動作が得られないことです (つまり、シフトに関係なく、正しい数の引数をシフトすることができません)。引数があるかどうか)。

次の両方を正しく実行したい:

foo a b c
foo -t 5 a b c

これを達成する最も簡単な方法は何ですか?追加のオプションのパラメーターを使用したい場合があるため、ハックではないソリューションをお勧めします。

4

2 に答える 2

6

問題は、 をリセットしないことです。$OPTINDそのため、呼び出すたびfooに、最後に処理されたオプション インデックスの後に始まる引数が調べられます。例えば:

# $OPTIND is now 1
foo -t opt arg1 arg2 arg3
# the above recognizes -t opt as an option, and sets $OPTIND to 3

# $OPTIND is now 3
foo arg4 arg5 arg6
# the above recognizes that arg6 is not an option, so it leaves $OPTIND at 3

解決策は、明示的に に設定して、$OPTIND内でローカライズすることです。foo1

foo() {
    baz=10
    local OPTIND=1
    while getopts ":t:" option; do
        case "$option" in
        t) baz=$OPTARG ;;
        esac
    done
    shift $((OPTIND - 1))
    bar -t $baz $1 $2 $3
}

(ローカライズを行っている間に、おそらくローカライズもしたいと思うでしょう$baz。)

于 2013-02-01T23:00:30.640 に答える
4

It appears that you're trying to write a bash function, not a bash script. OPTIND is set to 1 when the shell/script is invoked, but not when a function is invoked, so subsequent function calls with different arguments would continue parsing at the same point.

If you want to keep it as a function, you can reset it manually:

foo() {
    OPTIND=1
    baz=10
    while getopts ":t:" option; do
        case "$option" in
        t) baz=$OPTARG ;;
        esac
    done
    echo $OPTIND
    shift $((OPTIND - 1))
    echo bar -t $baz $1 $2 $3
}
于 2013-02-01T22:59:27.697 に答える