LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (http://www.linuxquestions.org/questions/linux-general-1/)
-   -   Handling null options in a bash script which ought to have a value (http://www.linuxquestions.org/questions/linux-general-1/handling-null-options-in-a-bash-script-which-ought-to-have-a-value-711932/)

dairo 03-16-2009 06:57 AM

Handling null options in a bash script which ought to have a value
 
I am having a shell script that is triggered by an external program. This external program starts the shell script with a few options and values. The problem here is that the external script does not always fill all the options with values,it sometimes leaves option on the command line without any value attached to it. In that case the options which does not have a value assumes the next option to be its value

************Program code************************************
cat testing
#!/bin/bash
while getopts c:l:g:u:s:t:a:e:y:z option
do
case ${option} in
c) c=${OPTARG};;
l) l=${OPTARG};;
s) s=${OPTARG};;
g) g=${OPTARG};;
t) t=${OPTARG};;
a) a=${OPTARG};;
e) e=${OPTARG};;
u) u=${OPTARG};;
y) y=${OPTARG};;
z) z=${OPTARG};;
\?) echo " usage error"
exit;
esac
done

echo "c=$c"
echo "l=$l"
echo "s=$s"
echo "t=$t"
echo "a=$a"
echo "e=$e"
echo "g=$g"
echo "u=$u"
echo "y=$y"
echo "z=$z"
**********************End of program**************************

eg :-
./testing -a val1 -l val2 -g -u val4
output:-
c=
l=val2
s=
t=
a=val1
e=
g=-u
u=
y=
z=


Here we see that -g option assumes that -u is a value fed to it. This way I am loosing out on the last value val4. Is there a work around for this problem in bash?

tronayne 03-16-2009 07:13 AM

Try it like this (with the double quotes); this is Korn shell (so "print -u2" might not work for you) but it should give you the idea:
Code:

#      define a fatal error function
function fatal
{
        print -u2 "${1}"
        exit 1
}
#      initialize flags to null
aflag=
bflag=
#      define usage message
USAGE="Usage:\t${0} [-a value] [-b value] args"
#      process command line arguments
while getopts :?a:b: name
do
        case ${name} in
        a)      aflag=1
                aval="${OPTARG}";;
        b)      bflag=1
                bval="${OPTARG}";;
        :)      print -u2 "${0}:\t${OPTARG} requires a value"
                fatal "${USAGE}";;
        \?)    print -u2 "${0}:\tunknown option"
                fatal "${USAGE}";;
        esac
done
if [ ! -z "${aflag}" ]
then
        print "Option -a ${aval} specified"
fi
if [ ! -z "${bflag}" ]
then
        print "Option -b ${bval} specified"
fi
shift $((${OPTIND}-1))
if [ "$*" ]
then
        print "Remaining arguments are:\t${*}"
fi
exit 0

The problem is that you're not trapping an option when an argument is required (that's what "colon)" is for).

[EDIT]
You know, I've been fooling around with this and, dang it, there just doesn't seem to be anything doable so that the problem you've described will not happen if an option does not have a required argument. You can have getopts require a numeric or alpha (or, for that matter, alphanumeric) argument and that will help sometimes but just a not show the next option as the argument value, well, I can't see a way to do that.

You mention that another application is invoking the shell program; have you considered evaluating the arguments there; i.e., if an argument is null, don't invoke the shell program? That might be a more useful alternative (you know, if you don't have what you need to keep going, quit rather than make a mess).

Sorry, this one hit my limit switch and crashed.

dairo 03-16-2009 12:27 PM

Hi tronayne,
Thank you very much for the quick response. My apologies, looks like I have slightly misquoted the problem. The code you have written definitely retrieves the values that were otherwise lost.But still the problem of an option without a value eating the adjacent option remains.
Here my requirement is to capture the value along with the right option.In the new script I will not be sure what the value really means as it only displays the remaining arguments, after which I still don't know what they mean.
This is what I did with the new code:
Code:


#!/bin/ksh
#      define a fatal error function
function fatal
{
        print -u2 "${1}"
        exit 1
}
#      initialize flags to null
aflag=
bflag=
cflag=
dflag=
#      define usage message
USAGE="Usage:\t${0} [-a value] [-b value] args"
#      process command line arguments
while getopts :?a:b:c:d: name
do
        case ${name} in
        a)      aflag=1
                aval="${OPTARG}";;
        b)      bflag=1
                bval="${OPTARG}";;
        c)      cflag=1
                cval="${OPTARG}";;
        d)      dflag=1
                dval="${OPTARG}";;
        :)      print -u2 "${0}:\t${OPTARG} requires a value"
                fatal "${USAGE}";;
        \?)    print -u2 "${0}:\tunknown option"
                fatal "${USAGE}";;
        esac
done
if [ ! -z "${aflag}" ]
then
        print "Option -a ${aval} specified"
fi
if [ ! -z "${bflag}" ]
then
        print "Option -b ${bval} specified"
fi
if [ ! -z "${cflag}" ]
then
        print "Option -c ${cval} specified"
fi
if [ ! -z "${dflag}" ]
then
        print "Option -d ${dval} specified"
fi
shift $((${OPTIND}-1))
if [ "$*" ]
then
        print "Remaining arguments are:\t${*}"
fi
exit 0

Test results of this script yielded the following:-
Code:

./testing  -a -b bbb -d -c
Option -a -b specified
Remaining arguments are:        bbb -d -c

What we see here is that -b gets assigned to "a" and the actual value of b (bbb) is detached from it. After this I will be left with a string of characters (bbb -d -c)which I will not be able to use intelligently.

Further elaborating, this script is triggered by a very rigid process written in java or c++ (I am not really sure) where it says:

Code:

/home/testing -a %access% -c %canceluser% -l %lenght% -s %setuser% -g %get% -t %trigger% -e %extratext% -u %user% -y %uptime% -z %create%
This is a fixed line from the program, now in reality this script will not always have values for all the variables placed within the % sign. This is when we come up with my problem. An example is like this
Code:

/home/testing -a 10:30 -c -l five -s smith -g get -t -e adding up things -u smith -y -z
What we see here is that a number of options like c,t,y,z do not have values. This kind of conditions should not affect the script, this script is a multi utility script which changes its behavior based on the available variable values. Hence I must some how be able to get the right values into the right variables.


All times are GMT -5. The time now is 05:56 PM.