3

I'm trying to use the ksh built-in getopts to manage runtime options for my ksh code.

I keep on getting the error: "unknown option argument value" when using an option that requires and argument.

Here's the offending code:

$ cat usage.sh
#!/bin/ksh
#set -xv

USAGE=$'[-?\n@(#)$Id: '"script_name"
USAGE+=$'\n'"script_version"$' $\n]'
USAGE+="[m:mode?Sets notification mode.]:[mode:=ALL]"
USAGE+="{[mode=SMS?SMS notification][mode=MAIL?EMAIL notification][mode=ALL?EMAIL and SMS notification]}"

while getopts "$USAGE" optchar;
    do
        case $optchar in
            m)  case "$OPTARG" in
                    MAIL) echo -e "-m MAIL:\tOK!"
                        ;;
                    SMS) echo -e "-m SMS:\tOK!"
                        ;;
                    ALL) echo -e "-m ALL:\tOK!"
                        ;;
                esac
                ;;

        esac
    done

And here some output:

$ ./usage.sh --man
SYNOPSIS
  ./usage.sh [ options ]

OPTIONS
  -m, --mode=mode Sets notification mode.
                    mode=SMS
                          SMS notification
                    mode=MAIL
                          EMAIL notification
                    mode=ALL
                          EMAIL and SMS notification
                  The default value is ALL.

IMPLEMENTATION
  version         script_name script_version

$ ./usage.sh -m SMS
./usage.sh: -m: SMS: unknown option argument value
Usage: ./usage.sh [-m mode]

$ ./usage.sh -m pippo
./usage.sh: -m: pippo: unknown option argument value
Usage: ./usage.sh [-m mode]

I came up with that horribly complex optstring following O'Reilly's - Learning the Korn Shell.

If I comment the fourth USAGE definition line the option argument value that's what I get:

$ ./usage.sh --man
SYNOPSIS
  ./usage.sh [ options ]

OPTIONS
  -m, --mode=mode Sets notification mode. The default value is ALL.

IMPLEMENTATION
  version         script_name script_version

$ ./usage.sh -m SMS
-m SMS: OK!

$ ./usage.sh -m pippo
(nothing)

Which I understand as getopts not checking for argument allowed values.

How can I have getopts check against unallowed argument values, in a way that it doesn't block allowed ones?

$ ksh --version
  version         sh (AT&T Research) 93u+ 2012-08-01
1

It appears you were setting the "ALL" mode option twice:

USAGE+="[m:mode?Sets notification mode.]:[mode:=ALL]"
USAGE+="{[mode=SMS?SMS notification][mode=MAIL?EMAIL notification][mode=ALL?EMAIL and SMS notification]}"

Simply remove the first one:

USAGE+="[m:mode?Sets notification mode.]:"
USAGE+="{[mode=SMS?SMS notification][mode=MAIL?EMAIL notification][mode=ALL?EMAIL and SMS notification]}"
  • I think the first time it describes the argument: name, defalut value, etc. the second one describes the allowed values. I tried your suggestion but didn't work (no argument description in --? mode and no argument filter) – Dariopnc Aug 23 '16 at 7:42
0

Posting this as memo, the following code works as intended:

#!/bin/ksh
#set -xv

USAGE=$'[-?\n@(#)$Id: '"script_name"
USAGE+=$'\n'"script_version"$' $\n]'
USAGE+="[m:mode?Sets notification mode.]:[mode:=ALL]"
USAGE+="{[S:SMS?SMS notification][M:MAIL?EMAIL notification][A:ALL?EMAIL and SMS notification]}"

while getopts "$USAGE" optchar;
    do
        case $optchar in
            m)  case "$OPTARG" in
                    M) echo -e "-m MAIL:\tOK!"
                        ;;
                    S) echo -e "-m SMS:\tOK!"
                        ;;
                    A) echo -e "-m SA:\tOK!"
                        ;;
                esac
                ;;

        esac
    done

Here's the output:

$ ./usage.sh --man
SYNOPSIS
  ./usage.sh [ options ]

OPTIONS
  -m, --mode=mode Sets notification mode.
                    SMS   SMS notification
                    MAIL  EMAIL notification
                    ALL   EMAIL and SMS notification
                  The default value is ALL.

IMPLEMENTATION
  version         script_name script_version

$ ./usage.sh -m SMS
-m SMS: OK!

$ ./usage.sh -m pippo
./usage.sh: -m: pippo: unknown option argument value
Usage: ./usage.sh [-m mode]

This way -m SMS is equivalent to -m S.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.