afc@shibaya.lonestar.org (Augustine Cano) (02/05/91)
I didn't anticipate the great response I got to my questions. This newsgroup is an important resource. Many thanks to the following people, whose summary of responses follow: ifas730@ccwf.cc.utexas.edu Neil Rickert <rickert@cs.niu.edu> bria!mike@uunet.UU.NET (Michael Stefanik) qpliu@lyman.pppl.gov (Peter Liu) raymond@math.berkeley.edu (Raymond Chen) Roger Cornelius <sherpa!rac@uunet.UU.NET> mcgrew@ichthous.Eng.Sun.COM (Darin McGrew) ...!uunet!amc.com!stuart (Stuart Poulin) kinnersley@kuhub.cc.ukans.edu (Bill Kinnersley): In article <1991Jan27.044258.18779@shibaya.lonestar.org> I wrote: >I am trying to specify (at run time) an upper limit for a loop in a shell >script. In pseudo-code the ideal would be something like this: > >read i >for 0 to i >do >... >done Just about everybody suggested a while loop with 'expr' to increment the loop variable. A typical response was: echo "enter upper limit" read limit i=0 while test $i -lt $limit do # some processing that involves $i here i=`expr 1 + $i` done The second part of my question was the "double indirection", >var0=REAL_VALUE0 >var1=REAL_VALUE1 >var2=REAL_VALUE2 >var3=REAL_VALUE3 >var4=REAL_VALUE4 > >I want to manipulate variable names inside the above loop such that >I could display the "REAL VALUEx" based on the current value of $i. Here the solution was also unanimous: the eval command. One solution was: read limit i=0 while [ $i -lt $limit ] do eval echo '$'var$i i=`expr $i + 1` done "Here's an alternate way to use eval, and maybe a bit clearer." eval var='$'var$i echo $var But there's more! In addition to answering my specific questions, Roger Cornelius <sherpa!rac@uunet.UU.NET> also supplied the following, which allowed me to solve another problem I had but had not formulated in my original posting. "You need to add braces around a parameter when it's followed by a letter, digit, or underscore (see Parameter Substitution in your sh manual page). You might want to read about eval in the sh man page also. x=2 y=5 while test ${x}${y} -gt 0 do y=`expr $y - 1` echo ${x}${y} test $y -eq 0 && x=`expr $x - 1` y=9 done Also, ...!uunet!amc.com!stuart (Stuart Poulin) added a default value: #Loop a default of Ulimit times. I never start at zero as a count. Ulimit=10 echo enter upper limit read Ans i=1 while [ $i -le ${Ans:-$Ulimit} ] do echo Loop Interation $i eval echo \$Var$i i=`expr $i + 1` done Again, many thanks to everyone. -- Augustine Cano INTERNET: afc@shibaya.lonestar.org UUCP: ...!{ernest,egsner}!shibaya!afc
steve@acorn.co.uk (Steve "daffy" Hunt) (02/12/91)
In article <1991Feb5.003613.21081@shibaya.lonestar.org> afc@shibaya.lonestar.org (Augustine Cano) writes: > > >I didn't anticipate the great response I got to my questions. This >newsgroup is an important resource. Many thanks to the following people, >whose summary of responses follow: ... more deleted... I only just subscribed to this newsgroup, so this is rather late, but my favourite solution to the loop index problem is the following shell function (just inline it if your shell does not support functions). # usage: range start end [step] range () { echo "[li p ${3-1} + d si $2!<a] sa ${1}silax" | dc } I don't guarantee that your version of dc will be happy with that, but it works for me! Making it count backwards, etc, is left as an exercise. Steve -- Steve Hunt steve@acorn.co.uk
ccsdhd@gdt.bath.ac.uk (Dennis Davis) (02/13/91)
In article <5081@acorn.co.uk> steve@acorn.co.uk (Steve "daffy" Hunt) writes: >In article <1991Feb5.003613.21081@shibaya.lonestar.org> afc@shibaya.lonestar.org (Augustine Cano) writes: >> >> >>I didn't anticipate the great response I got to my questions. This >>newsgroup is an important resource. Many thanks to the following people, >>whose summary of responses follow: > >... more deleted... > >I only just subscribed to this newsgroup, so this is rather late, but >my favourite solution to the loop index problem is the following shell >function (just inline it if your shell does not support functions). > ># usage: range start end [step] > >range () { > echo "[li p ${3-1} + d si $2!<a] sa ${1}silax" | dc >} > >I don't guarantee that your version of dc will be happy with that, but >it works for me! Making it count backwards, etc, is left as an exercise. > > Steve > >-- > Steve Hunt steve@acorn.co.uk I've always found that languages such as 'dc' are very much write-only languages. This is probably a reflection on me rather than on the language itself. I'd prefer to write the above more verbosely using 'bc', as something like: range () { set `echo $@ | tr '-' '_'` echo "if (${3-1} < 0) { for (i=$1; i>=$2; i=i+${3-1}) i } if (${3-1} > 0) { for (i=$1; i<=$2; i=i+${3-1}) i }" | bc } The 'set' command is there as a sop to syntactic sugar. 'dc' and 'bc' require that negative numbers are preceeded by a underline instead of a minus sign. The 'set' command enables you to write them more naturally using a minus sign, eg 'range -5 -10 -1'. The above has (for me) the overwhelming advantages that I can understand it both now *and* in the future. ... all this is purely academic of course. No doubt there are far more elegant solutions using awk, perl etc etc ... -- Dennis Davis JANET: D.H.Davis@UK.AC.BATH University of Bath UUCP: ...!mcsun!ukc!gdr!D.H.Davis Bath, BA2 7AY EARN/BITNET: D.H.Davis%uk.ac.bath@UKACRL England INTERNET: D.H.Davis%bath.ac.uk@nsfnet-relay.ac.uk