Its not related to getopts Run the following(with set -x probably): foo() { echo "$1" ;} foo -i oIFS=$IFS IFS=- foo -i IFS=$oIFS foo() { echo $1 ;} foo -i IFS=- foo -i
If you run your code with set -x, you would notice that the real cause is that $err_opts is not quoted. You set IFS and are bitten by word splitting. ----- Original Message ---- > From: Steven W. Orr <ste...@syslang.net> > To: bug-bash@gnu.org > Sent: Tue, 26 April, 2011 6:41:49 PM > Subject: Re: Is this an IFS bug in getopts? > > On 4/26/2011 12:02 PM, DJ Mills wrote: > > On Tue, Apr 26, 2011 at 11:42 AM, Steven W. Orr<ste...@syslang.net> wrote: > > > >> GNU bash, version 4.0.35(1)-release (x86_64-redhat-linux-gnu) > >> > >> I ran a program that was supposed to die with an error message that said: > >> > >> Invalid format: example: 2.103.269.28-1-3 > >> > >> Instead, it died with: > >> > >> i -- Invalid format: example: 2.103.269.28-1-3 > >> > >> I traced the problem back to a call to getopts. It turns out that when I > >> called getopts, I had set IFS='-'. It never occurred to me that I could > >> impact the function of getopts by setting IFS. > >> > >> The old code was this: > >> DRVREV="$1" > >> IFS=- > >> set -- $DRVREV > >> (( $# == 3 )) || die -i -- 'Invalid format: example: 2.103.269.28-1-3' > >> > >> I can fix the problem easily by saying > >> > >> oldIFS="$IFS" > >> DRVREV="$1" > >> IFS=- > >> set -- $DRVREV > >> IFS="$oldIFS" > >> (( $# == 3 )) || die -i -- 'Invalid format: example: 2.103.269.28-1-3' > >> > >> So here we are. > >> 1. Should getopts be documented to say that it uses IFS? > >> 2. Should getopts be hardcoded to use the dash as the option delimiter? > >> 3. Is the current functionality correct the way it is and I'm just looking > >> at it wrong? > >> > >> TIA :-) > >> > >> > > I don't see getopts anywhere in that example. It would also help to know > > what your > > die() function is, as I suspect that may be causing the issue. > > Fair enough. > > err was created as a simple echo that went to stderr. Then I added -i so > that >it would allow itself to read from stdin after it processed its arguments. > > die is just a call to err followed by a call to exit. It captures the -i and >passes it through to err. It also accepts a -s to specify an exit code. > > Also, the die call is routinely made with -- because sometimes the args to > be >echoed can begin with a -. > > err() > { > typeset opt > typeset opt_i=0 > OPTIND=1 > while getopts ':-i' opt "$@" > do > case $opt in > i) > opt_i=1 > ;; > *) > echo "Illegal option to err: ${@:((OPTIND-1)):1}" 1>&2 > exit 1 > ;; > esac > done > shift $((OPTIND-1)) > (( $# != 0 )) && echo -e "$@" 1>&2 > (( opt_i )) && cat 1>&2 > } > > die() > { > typeset opt > typeset opt_s=1 > typeset opt_i=0 > typeset err_opts= > OPTIND=1 > while getopts ':is:' opt "$@" > do > case $opt in > i) > opt_i=1 > err_opts='-i' > ;; > s) > opt_s=$OPTARG > ;; > *) > err "Illegal option to die: ${@:((OPTIND-1)):1}" > exit 1 > ;; > esac > done > shift $((OPTIND-1)) > err $err_opts -- "$@" > exit $opt_s > } > > > > -- Time flies like the wind. Fruit flies like a banana. Stranger things have > >.0. > happened but none stranger than this. Does your driver's license say Organ ..0 > Donor?Black holes are where God divided by zero. Listen to me! We are all- 000 > individuals! What if this weren't a hypothetical question? > steveo at syslang.net > >