getops : 入力オプションを制限する条件

getops : 入力オプションを制限する条件

4 つの入力オプション (x:m:b:v) を受け入れるシェル スクリプトがあります。ただし、入力オプションを次のように制限したいと思います。

条件1

1. Accept option x or x and b
   eg: sh script -x <arg> (or)             ;will execute function a defined in script
       sh script -x <arg> -b               ;will execute the functions a and b

条件2

2. Accept option m or m and b
   eg: sh script -m <arg> (or)     ;execute function c
       sh script -m <arg1> -b   ;should execute function for c and b

条件3

3. Option both x and m should not be passed together.
   This will print usage(how to use the input options) function.

条件4

4. Option v. This should not be passed with any other option.
   eg: sh script -v <arg>  ; executs the function for v

これは if 条件と else 条件で実現できることはわかっていますが、条件のロジックを取得できません。

また、入力引数がまったく渡されない場合、またはすべての入力引数が渡された場合は、使用関数を実行する必要があります。

答え1

上記のコメントを説明する例として、FreeBSD からの抜粋を以下に示します/usr/src/bin/cp/cp.c

while ((ch = getopt(argc, argv, "HLPRafilnprsvx")) != -1)
        switch (ch) {
        case 'H':
                Hflag = 1;
                Lflag = 0;
                break;
        case 'L':
                Lflag = 1;
                Hflag = 0;
                break;
        ...
        case 'l':
                lflag = 1;
                break;
        ...
        case 's':
                sflag = 1;
                break;
        case 'v':
                vflag = 1;
                break;
        case 'x':
                fts_options |= FTS_XDEV;
                break;
        default:
                usage();
                break;
        }

上記では、Hflag、Lflag、lflag、sflag などのブール変数が多数設定されていることに注意してください。これにより、コードでフラグ間のブール関係をテストできるだけでなく、1 つのフラグの存在によって別のフラグをアクティブ化したり、別のフラグをオーバーライドしたりすることもできます。また、ユーザーが未定義のオプション フラグを指定した場合、ステートメントdefaultの句によって呼び出しswitchが強制されることにも注意してください。usage()

mflag&&を許可しないなどのフラグの除外に関してはxflag、cp.c に同様のケースがあります。

if (lflag && sflag)
        errx(1, "the -l and -s options may not be specified together");

bash以下は、あなたの例に合わせてさらに適応させた、C からのコードの可能な翻訳です。

flagb=
flagm=
flagv=
flagx=

while getopts "bm:vx:" ch
do

        case "$ch" in
        [bv])
                eval flag$ch=1
                printf 'flag%s set\n' "$ch"
                ;;
        [mx])
                eval flag$ch=1
                eval arg$ch=\"$OPTARG\"
                printf 'flag%s set\n' "$ch"
                printf 'arg%s is "%s"\n' "$ch" "$OPTARG"
                ;;
        -)
                break
                ;;
        esac

done

[[ $OPTIND > 1 ]] && shift $(($OPTIND-1))

if [[ "$flagv" ]]
then
        if [[ -n "$flagb$flagm$flagx" ]]
        then
                printf 'error: -v cannot be used with any other flags\n' >&2
                exit 2
        fi
fi

if [[ "$flagm$flagx" = "11" ]]
then
        printf 'error: -m and -x cannot be used together\n' >&2
        exit 2
fi

if [[ "$flagb" ]] && ! [[ "$flagm$flagx" ]]
then
        printf 'error: -b requires either -m or -x\n' >&2
        exit 2
fi

[[ "$flagb" ]] && printf 'b flag is set\n'
[[ "$flagm" ]] && printf 'm flag is set, arg is "%s"\n' "$argm"
[[ "$flagv" ]] && printf 'v flag is set\n'
[[ "$flagx" ]] && printf 'x flag is set, arg is "%s"\n' "$argx"

[[ "$@" ]] && {
        printf 'remaining arguments:'
        printf ' "%s"' "$@"
        printf '\n'
}

関連情報