1

引数の解析を含む bash スクリプトを作成しています。使用法は次のとおりです。

$ ./my_script.sh -a ARG_1 -b ARG_2 [-c LIST_OF_ARGS...]

を使用して、それぞれの値とgetoptsを解析-aして取得することができます。ユーザーが最後の引数として配置した場合にのみ、のすべての値を含むリストを取得して作成することもできます。-bARG_1ARG_2-c-cLIST_OF_ARGS...

-cしかし、ユーザーに最後のフラグとして挿入を強制したくありません。たとえば、スクリプトを次のように呼び出すことができれば素晴らしいでしょう。

$ ./my_script.sh -b ARG_2 -c V1 V2 V3 -a ARG_1

これが私の現在のコードです:

while getopts a:b:c opt
do
    case $opt in
        a)
            A_FLAG=$OPTARG
            ;;
        b)
            B_FLAG=$OPTARG
            ;;
        c)
            # Handle values as regular expressions
            args=("$@")
            C_LIST=()
            for (( i=$OPTIND-1 ; i <= $#-1 ; i++ ))
            do
                C_LIST=("${C_LIST[@]}" ${args[$i]})
            done
            ;;
        ?)
            usage
            ;;
    esac
done
4

3 に答える 3

1

ここで質問です: なぜ -c オプションがあるのですか?

完全な使用法に値のリストが含まれる場合、 -c オプションを指定せずに -a および -b オプションのみを許可し、残りは のように通常の引数で./myscript.sh -a ARG_1 -b ARG_2 [argument ...]ある場合、引数はオプションです (-c オプションとそのオプションのように)。引数はあなたの使用例にありますか?

次に、あなたの質問は「プログラムのオプションと引数を散在させるにはどうすればよいですか」になり、それに対して私は次getoptsのように答えます。そうでなければ。」

もちろん、解析は難しい方法です。別のオプションまたはオプションの終わりに遭遇しない限り、 -c の後に値をリストに追加する別の可能性があります。

C_LIST=()
while getopts a:b:c: opt; do
    #Skipping code...
    c)
        C_LIST+="$OPTARG"
        shift $(expr $OPTIND - 1)
        while [ -n "$1" ] && [ $(printf "%s" "$1" | grep -- '^[^-]') ]; do
            C_LIST+="$1"
            shift
        done
        OPTIND=1
        ;;

getopts の動作は模倣されます: OPTARG が '-' 文字で始まる場合でも保持されますが、OPTARG の後では、'-' 文字で始まる文字列は単に -n などの無効なオプションである可能性があります。echo の代わりに printf を使用しました。これは、bash に組み込まれているものなど、一部のバージョンの echo には -e オプションがあり、ループの継続を許可する場合と許可しない場合がありますが、これは望ましくありません。grep 式はこれを防ぐ必要がありますが、そのバージョンの echo が -e'hello' を許可するかどうかは誰にもわかりません。不要かもしれませんが、チャンスをつかむ必要はありません。

個人的には、できればこの動作は避けたいと思いますが、そもそもなぜこの動作を求めているのか理解できません。私が何かを推奨するとしたら、/path/to/script -a ARG_1 -b ARG_2 [argument ...]他の可能な実装の選択肢よりも、より一般的なスタイルをお勧めします。

于 2013-07-25T23:57:07.067 に答える
1

私のシステムには、/usr/share/doc/util-linux/examples/getopt-parse.bashファイルがあります。結果を変数に入れgetopt、位置パラメータをその変数に設定します。次に、switchあなたのものと同様のものを使用shiftしますが、見つかったときに引数を削除するために使用します。

同様のことを行うこともできますが、オプションを取得するか引数がなくなるまで-cオプションを使用します。shift


または、現在のソリューションを使用するだけで十分かもしれませんが、ループの後に変数を設定することを忘れないでください。OPTIND

于 2013-07-25T13:28:51.483 に答える
1

-cフラグの検出とそれに関連する処理を分離する必要があります。たとえば、次のようなものです。

while getopts a:b:c opt
do
    case $opt in
        a)
            A_FLAG=$OPTARG
            ;;
        b)
            B_FLAG=$OPTARG
            ;;
        c)
            C_FLAG=1
            ;;
        ?)
            usage
            ;;
    esac
done

# discard all of our options.
shift `expr $OPTIND - 1`

if [ "$C_FLAG" = 1 ]; then
            # Handle values as regular expressions
            args=("$@")
            C_LIST=()
            for (( i=0 ; i <= $#-1 ; i++ ))
            do
                C_LIST=("${C_LIST[@]}" ${args[$i]})
            done
fi

このスクリプトは、すべてのコマンド ライン オプション処理するまで、すべての非オプション引数を収集しません。

于 2013-07-25T13:28:58.917 に答える