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

2 Answers 2

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]}"
1
  • 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, 2016 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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .