Manish Kumar
Manish Kumar

Reputation: 10502

Shell Script is not reading optional parameter correctly

I have this script file:

#!/bin/sh

Show_Error() {
        echo -e "\033[31m ERROR \033[0m $1"
}

if [ "$1" = "-help" ]
then
    echo "<input> - input file name or input URL"
else


for i in "$@"
do
case $i in
    -l=*|--ddloc=*)
    DDLOC="${i#*=}"
    shift # past argument=value
    ;;
    -l|--ddloc)
    shift # past argument
    DDLOC="$1"
    shift # past value
    ;;
    *)
          # unknown option
    ;;
esac
done

if [ -z "$DDLOC" ]
then
       Show_Error 'File is missing. Use -l or --ddloc.'
else
echo "Location::: $DDLOC"
fi
fi

If i run command: ./tdl2ddlgen.sh -s sssss -m lll -l LOC

It is giving "Location::: sssss" intead of "Location::: LOC"

Upvotes: 0

Views: 39

Answers (1)

jhnc
jhnc

Reputation: 16829

You can consider that for i in "$@" copies all the values from $@ and then sets $i to each in turn. You can watch what is happening by instrumenting your code:

for i in "$@"
do
echo "\$i = $i; \$@ = ($@)"
case $i in
    # ...

giving output:

$i = -s; $@ = (-s sssss -m 111 -l LOC)
$i = sssss; $@ = (-s sssss -m 111 -l LOC)
$i = -m; $@ = (-s sssss -m 111 -l LOC)
$i = 111; $@ = (-s sssss -m 111 -l LOC)
$i = -l; $@ = (-s sssss -m 111 -l LOC)
$i = LOC; $@ = (-m 111 -l LOC)
Location::: sssss

What is actually going wrong is that you don't shift away $1 when you get an unknown option. If you add the shift:

for i in "$@"
do
echo "\$i = $i; \$@ = ($@)"
case $i in
    -l=*|--ddloc=*)
    DDLOC="${i#*=}"
    shift # past argument=value
    ;;
    -l|--ddloc)
    shift # past argument
    DDLOC="$1"
    shift # past value
    ;;
    *)
          # unknown option
    shift
    ;;
esac
done

then you will get the result you were expecting:

$i = -s; $@ = (-s sssss -m 111 -l LOC)
$i = sssss; $@ = (sssss -m 111 -l LOC)
$i = -m; $@ = (-m 111 -l LOC)
$i = 111; $@ = (111 -l LOC)
$i = -l; $@ = (-l LOC)
$i = LOC; $@ = ()
Location::: LOC

although the behaviour is still not quite correct - LOC argument is processed twice. To prevent the double-processing, rather than copying $@ for your loop, you could do:

while [ -n "$1" ]
do
case $1 in
    # ...

Upvotes: 1

Related Questions