magicalo
magicalo

Reputation: 473

getopts truncates argument value

I need to pass a string value containing spaced as option in myscript.sh The code looks like this:

while getopts "m:i:t:" OPTION
do
 case $OPTION in
     m)
         M=$OPTARG
         echo M: $M
         ;;
     i)
         I=$OPTARG
         echo I: $I
         ;;
     t)
         T=$OPTARG
         echo T: $T
         ;;
     ?)
         usage
         exit
         ;;
 esac
done

It works just fine when I call it directly on the command line:

./myscript.sh -m 1 -i '0 1 2 3' -t '2142'
M: 1
I: 0 1 2 3
T: 2142

However, I need to pass the -i as a string variable and I cannot get it to work. The string for option -i gets truncated and option -t does not even come through (possibly a new line).

I='0 1 2 3'
./myscript.sh -m 1 -i "'"$I"'" -t '2142'
M: 1
I: '0

I='0 1 2 3'
II="'"$(echo $I)"'"
./myscript.sh -m 1 -i $II -t '2142'
M: 1
I: '0

Any suggestions? Thanks!

Upvotes: 1

Views: 1023

Answers (1)

Cascabel
Cascabel

Reputation: 496892

Why are you quoting like that when you try to run it? This I'm pretty sure this is what you meant to do:

./myscript.sh -m 1 -i "$I" -t 2142

Double quotes treats all characters inside them as literal, except a few things, including $, which allows variables to be expanded. Single quotes stop variable expansion as well. They each protect the other type of quote, so that "'" is just a ' character, and '"' is just a " character.

This means that "'"$I"'" turns into '0 1 2 3', with no special meaning for the single quotes, and no protection for the spaces - you might also write it as \'0 1 2 3\'. The spaces, being unprotected, split up words, so the first word is \'0. Your script therefore sees that as the value for the option, and 1, 2, and 3' as extra arguments. You can see this if after your while loop you add shift $((OPTIND - 1)) to shift away the parsed options, and then echo "arguments: $@" after your option parsing. You'll also see that since getops expects all the options together at the front, this has caused you to miss out on the -t option, treating it as an argument too.

Upvotes: 3

Related Questions