[comp.unix.wizards] evaluating ${10} and above in sh/ksh

chrisb@risky.Convergent.COM (Chris Bertin) (08/11/90)

There doesn't seem to be a way, in sh or ksh, to evaluate $10 and higher.
$10 and higher are evaluated as ${1}0, ${1}1, etc...
		     instead of ${10}, ${11}, etc...
I have tried many different ways and they all fail. Do you know one
that will work?

#! /bin/sh

set a b c d e f g h i j k l

arg=0

while [ $arg -le $# ]; do
	echo "evaluating \$$arg"
	eval echo $"$arg"
	eval echo $"${arg}"
	eval echo "$`eval echo $arg`"
	# Now, some of the crazy things I tried.
	# ( The parens are there when eval causes an error )
	echo "\${$arg} results in \c"
	( eval echo "\${$arg}" )
	echo "$`echo '{'``eval echo $arg``echo '}'` results in \c"
	( eval echo "$`echo '{'``eval echo $arg``echo '}'`" )
	arg=`expr $arg + 1`
done
-- 
Chris Bertin		|   chrisb@risky.Convergent.COM
Unisys			|		or
(408) 435-3762		| ...!uunet!pyramid!ctnews!risky!chrisb

hartman@ide.com (Robert Hartman) (08/13/90)

In article <514@risky.Convergent.COM> chrisb@risky.Convergent.COM (Chris Bertin) writes:
>There doesn't seem to be a way, in sh or ksh, to evaluate $10 and higher.
>$10 and higher are evaluated as ${1}0, ${1}1, etc...
>		     instead of ${10}, ${11}, etc...
>I have tried many different ways and they all fail. Do you know one
>that will work?
>

This is what the shift builtin is for:

# sort out arguments
while [ $# -gt 0 ] ; do
    case $1 in
        -a)  a=true  ;;
        -b)  b=true  ;;
 	-*)  "echo illegal option" ;;
	*)   "$files $i"   ;;
    esac
    shift
done

This will process through all of your arguments and build a list of filenames.
It doesn't work if options can have arguments of their own.  For cases like
this, I use getopts to parse out the command line.  There's a good example in
the getopts man page.

-r

maart@cs.vu.nl (Maarten Litmaath) (08/14/90)

In article <514@risky.Convergent.COM>,
	chrisb@risky.Convergent.COM (Chris Bertin) writes:
)There doesn't seem to be a way, in sh or ksh, to evaluate $10 and higher.
)$10 and higher are evaluated as ${1}0, ${1}1, etc...
)		     instead of ${10}, ${11}, etc...

Alas...  POSIX fixes this though: ${10} will work.

)I have tried many different ways and they all fail. Do you know one
)that will work?

	set a b c d e f g h i j k l m

	argv()
	{
		shift $1 2> /dev/null
		echo "$1"
	}

	echo `argv 10 "$@"`
	echo `argv 11 "$@"`
	echo `argv 20 "$@"`

Beware of "$@": many shells will expand it to a single null string if
there are no positional parameters present at all!  A safe workaround
is:
	${1+"$@"}

Check it out in the manual!
--
   "UNIX was never designed to keep people from doing stupid things, because
    that policy would also keep them from doing clever things."  (Doug Gwyn)

gorpong@ping.uucp (Gordon C. Galligher) (08/14/90)

In article <514@risky.Convergent.COM> chrisb@risky.Convergent.COM 
(Chris Bertin) writes:
>There doesn't seem to be a way, in sh or ksh, to evaluate $10 and higher.
>$10 and higher are evaluated as ${1}0, ${1}1, etc...
>		     instead of ${10}, ${11}, etc...
>I have tried many different ways and they all fail. Do you know one
>that will work?

I realize this is hardly what you wish to read, but the only way to gain
access to the others is by using 'shift' to get them.  You could, on the
other hand set up a loop to grab all of them into your own variables:

	argv0=$0
	start=1
	pred=argv
	for i
	do
		eval "${pred}${start}='$i'"	# Be sure to quote the $i !!
		start=`expr $start + 1`
	done
	argc=`expr $start - 1`

This would give you variables $argv0, $argv1, $argv2 up to and including
$argv$argc.  To simply print them out:

	echo "	0 - $argv0"
	start=1
	while [ $start -le $argc ]
	do
		echo "	$start - `eval echo '$'${pred}${start}`" # Yes, ugly
		start=`expr $start + 1`
	done

No, it is not pretty, but it is workable.  There may not be many times you
would want to print option 'x' without knowing what 'x' was.  If you
always wanted to check the first option, then it is just $argv1.  If you
find yourself always parsing through the command line options, then you
should probably put a case inside of the for and then do with them what
you will.

		-- Gordon.
-- 
Gordon C. Galligher	9127 Potter Rd. #2E	Des. Plaines, Ill.	60016
     telxon!ping%gorpong@uunet.uu.net (not tested)  (Is this even legal??)
     ...!uunet!telxon!ping!gorpong      (tested)    (And it works!)
"It seems to me, Golan, that the advance of civilization is nothing but an

mvadh@cbnews.att.com (andrew.d.hay) (08/14/90)

In article <514@risky.Convergent.COM>,
	chrisb@risky.Convergent.COM (Chris Bertin) writes:
"There doesn't seem to be a way, in sh or ksh, to evaluate $10 and higher.
"$10 and higher are evaluated as ${1}0, ${1}1, etc...
"		     instead of ${10}, ${11}, etc...

in ksh88, ${10}, ${11}, etc. are evaluated correctly, but YOU MUST
BRACE THE ARGUMENTS!  $10 and $11 are evaluated as you experienced.

-- 
Andrew Hay		+------------------------------------------------------+
Ragged Individualist	| 	You just have _N_O idea!  It's the difference    |
AT&T-BL Ward Hill MA	|	between _S_H_O_O_T_I_N_G a bullet and _T_H_R_O_W_I_N_G it!     |
a.d.hay@att.com		+------------------------------------------------------+

bd@hpopd.HP.COM (Bob Desinger) (08/14/90)

> There doesn't seem to be a way, in sh or ksh, to evaluate $10 and higher.

In /bin/sh this never worked, although individual vendors may have
modified their /bin/sh.  I don't know of any that have, by the way.

It looks like your ksh is broken.  Version 06/03/86 (or at least that
version shipped with HP-UX at 7.0 on Series 300 and 800) does the
right thing:

    set a b c d e f g h i j k l

    print 9 is $9, 10 is ${10}, 11 is ${11}, 12 is ${12}.

    alias i='echo Number 9'
    alias j='echo Number 10'
    alias k='echo Number 11'
    alias l='echo Number 12'
    eval $9
    eval ${10}
    eval ${11}
    eval ${12}
	
The new ksh88, Version 11/16/88, also does the right thing.  Both
versions of ksh generate the correct output:

    9 is i, 10 is j, 11 is k, 12 is l.
    Number 9
    Number 10
    Number 11
    Number 12

I invoked the script with `ksh script' and `ksh88 script'.   Then I
also tested it with a first line of `#! /usr/local/bin/ksh88' and
`#! /bin/ksh'.  All four cases generated the same output.  Uh, ksh88
isn't shipped with HP-UX; we bought it from the AT&T Toolchest.

Your script lines are considerably more complex than mine, though.  In
fact, I stopped trying to figure out what the script was trying to do
and just ran your script.  I mailed my output to you; we can follow
this up offline.  Summarize to the net?

-- bd