edh@ux.acs.umn.edu (Merlinus Ambrosius) (04/03/91)
In sh, I'd like to do something like a BASIC for loop. Say I have $FILES set to some number, and I'd like to go through a loop $FILES times. Can this be done in sh? Thanks! --eric
smazu@ameris.UUCP (Steven P. Mazurek) (04/04/91)
In article <3693@ux.acs.umn.edu>, edh@ux.acs.umn.edu (Merlinus Ambrosius) writes: > .....Say I have $FILES set to some number, and I'd like to go through > a loop $FILES times. Can this be done in sh? > You don't mention the type of shell your using, but for Bourne investigate the command expr(1). while [ $FILES -ne 0 ] # use strings if its more comfortable do .... things .... FILES=`expr $FILES - 1` done -- Steven P. Mazurek | Email: {uunet,bcr,lbesac}!ameris!smazu Ameritech Services | Schaumburg, IL USA 60010 | Phone : (708) 605-2858
jik@athena.mit.edu (Jonathan I. Kamens) (04/04/91)
In article <3693@ux.acs.umn.edu>, edh@ux.acs.umn.edu (Merlinus Ambrosius) writes: |> In sh, I'd like to do something like a BASIC for loop. Say I have $FILES |> set to some number, and I'd like to go through a loop $FILES times. Can |> this be done in sh? Yes. The trick is getting from the number to that many items that you can put into a for loop. Something like this FILES=10 for i in `jot $FILES`; do echo -n "*" done; echo "" will print ten asterisks and then a newline, if your echo supports "-n" and you have "jot". If you don't have "jot", you can get it from /help/dist on lilac.berkeley.edu. Alternatively, you can use awk to do the counting: FILES=10 for i in `echo $FILES | awk '{for(i=0;i<$1+0;i++){print i}; exit}'`; do echo -n "*" done; echo "" which will print the same as the loop above. You could also use expr and test to decrement the variable by one on each pass through the loop and check if it's zero, but that's very inefficient compared to the methods above, which require only one fork to set up the count for the entire loop. -- Jonathan Kamens USnail: MIT Project Athena 11 Ashford Terrace jik@Athena.MIT.EDU Allston, MA 02134 Office: 617-253-8085 Home: 617-782-0710
pefv700@perv.pe.utexas.edu (04/04/91)
In article <3693@ux.acs.umn.edu>, edh@ux.acs.umn.edu (Merlinus Ambrosius) writes... >In sh, I'd like to do something like a BASIC for loop. Say I have $FILES >set to some number, and I'd like to go through a loop $FILES times. Can >this be done in sh? > >Thanks! > --eric How about either while [ $FILES -gt 0 ] do # body FILES=`expr $FILES - 1` done or i=0 while [ $i -lt $FILES ] do # body i=`expr $i + 1` done Chris
miquels@maestro.htsa.aha.nl (Miquel van Smoorenburg) (04/04/91)
In article <3693@ux.acs.umn.edu> edh@ux.acs.umn.edu (Merlinus Ambrosius) writes: >In sh, I'd like to do something like a BASIC for loop. Say I have $FILES >set to some number, and I'd like to go through a loop $FILES times. Can >this be done in sh? POSIX states that sh(1) should be able to evaluate expressions, so you can do something like while [ $FILES != 0 ] do echo -n '* ' FILES=$[$FILES - 1] done But I haven't seen a sh anywhere that is already capable of doing this (not even the one I am writing myself for Minix... yet.). Maybe somebody knows if a new ksh can do this? -- +===============================+============================================+ | | | | Miquel van Smoorenburg, | It's nice to be important, | | miquels@maestro.htsa.aha.nl | but it's more important to be nice. | | | | +===============================+============================================+
jimr@hplsdv7.COS.HP.COM (Jim Rogers) (04/05/91)
/ hplsdv7:comp.unix.shell / edh@ux.acs.umn.edu (Merlinus Ambrosius) / 4:14 pm Apr 2, 1991 / In sh, I'd like to do something like a BASIC for loop. Say I have $FILES set to some number, and I'd like to go through a loop $FILES times. Can this be done in sh? Thanks! --eric ---------- Try the following: #!/bin/sh foo=10 count=0 while [ $count -lt $foo ] do echo $count count=`expr $count + 1` done The "expr" command evaluates arguments as an expression and writes the result to stdout. Jim Rogers Hewlett-Packard Company Colorado Springs, Colorado
rad@genco.bungi.com (Bob Daniel) (04/05/91)
In article <3693@ux.acs.umn.edu> edh@ux.acs.umn.edu (Merlinus Ambrosius) writes: >In sh, I'd like to do something like a BASIC for loop. Say I have $FILES >set to some number, and I'd like to go through a loop $FILES times. Can >this be done in sh? > for i in $FILES do ls -l $i .... or whatever to do with that file done If FILES="/etc/inittab /etc/passwd /etc/mnttab etc...", each file will be treated individually in the example above.
spicer@tci.UUCP (Steve Spicer) (04/05/91)
In article <2816@maestro.htsa.aha.nl> miquels@maestro.htsa.aha.nl (Miquel van Smoorenburg) writes: >In article <3693@ux.acs.umn.edu> edh@ux.acs.umn.edu (Merlinus Ambrosius) writes: >>In sh, I'd like to do something like a BASIC for loop. Say I have $FILES >>set to some number, and I'd like to go through a loop $FILES times. Can >>this be done in sh? > >POSIX states that sh(1) should be able to evaluate expressions, >so you can do something like >while [ $FILES != 0 ] >do > echo -n '* ' > FILES=$[$FILES - 1] >done > >But I haven't seen a sh anywhere that is already capable of doing this >(not even the one I am writing myself for Minix... yet.). >Maybe somebody knows if a new ksh can do this? ksh allows this (which I tested before posting) $ integer i=5 $ while (( i > 0 )) ; do > print $i > (( i = i - 1 )) >done 5 4 3 2 1 $ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Steven Spicer/spicer@tci.bell-atl.com Is your design so simple that there are obviously no deficiencies, or so complicated that there are no obvious deficiencies? -- suggested by a quote from C.A.R. Hoare
asg@sage.cc.purdue.edu (Bruce Varney) (04/05/91)
In article <2816@maestro.htsa.aha.nl> miquels@maestro.htsa.aha.nl (Miquel van Smoorenburg) writes: }In article <3693@ux.acs.umn.edu> edh@ux.acs.umn.edu (Merlinus Ambrosius) writes: }>In sh, I'd like to do something like a BASIC for loop. Say I have $FILES }>set to some number, and I'd like to go through a loop $FILES times. Can }>this be done in sh? } }POSIX states that sh(1) should be able to evaluate expressions, }while [ $FILES != 0 ] }do } echo -n '* ' } FILES=$[$FILES - 1] }done } No, but the new bash (version 1.07) can! ;-) } --------- ### ## Courtesy of Bruce Varney ### # aka -> The Grand Master # asg@sage.cc.purdue.edu ### ##### # PUCC ### # ;-) # # ;'> # ##
dattier@vpnet.chi.il.us (David W. Tamkin) (04/05/91)
miquels@maestro.htsa.aha.nl (Miquel van Smoorenburg) wrote in <2816@maestro.htsa.aha.nl>: | POSIX states that sh(1) should be able to evaluate expressions, | so you can do something like | while [ $FILES != 0 ] | do | echo -n '* ' | FILES=$[$FILES - 1] | done | But I haven't seen a sh anywhere that is already capable of doing this | (not even the one I am writing myself for Minix... yet.). | Maybe somebody knows if a new ksh can do this? Even an old ksh can do let FILES = $FILES - 1 or (( FILES = FILES - 1 )) David Tamkin PO Box 7002 Des Plaines IL 60018-7002 dattier@vpnet.chi.il.us GEnie:D.W.TAMKIN CIS:73720,1570 MCIMail:426-1818 708 518 6769 312 693 0591
]) (04/06/91)
In article <2816@maestro.htsa.aha.nl> miquels@maestro.htsa.aha.nl (Miquel van Smoorenburg) writes: >In article <3693@ux.acs.umn.edu> edh@ux.acs.umn.edu (Merlinus Ambrosius) writes: >>In sh, I'd like to do something like a BASIC for loop. Say I have $FILES >>set to some number, and I'd like to go through a loop $FILES times. Can >>this be done in sh? > >POSIX states that sh(1) should be able to evaluate expressions, >so you can do something like >while [ $FILES != 0 ] >do > echo -n '* ' > FILES=$[$FILES - 1] >done #### ksh fragment #### while [ $FILES -ge 0 ] do echo "$FILES" ((FILES -= 1)) # or ((FILES = $FILES - 1)) done #### ksh fragment #### ...Kris -- Kristopher Stephens, | (408-746-6047) | krs@uts.amdahl.com | KC6DFS Amdahl Corporation | | | [The opinions expressed above are mine, solely, and do not ] [necessarily reflect the opinions or policies of Amdahl Corp. ]
]) (04/06/91)
In article <2816@maestro.htsa.aha.nl> miquels@maestro.htsa.aha.nl (Miquel van Smoorenburg) writes: >In article <3693@ux.acs.umn.edu> edh@ux.acs.umn.edu (Merlinus Ambrosius) writes: >>In sh, I'd like to do something like a BASIC for loop. Say I have $FILES >>set to some number, and I'd like to go through a loop $FILES times. Can >>this be done in sh? > >POSIX states that sh(1) should be able to evaluate expressions, >so you can do something like >while [ $FILES != 0 ] >do > echo -n '* ' > FILES=$[$FILES - 1] >done > >But I haven't seen a sh anywhere that is already capable of doing this >(not even the one I am writing myself for Minix... yet.). >Maybe somebody knows if a new ksh can do this? #### ksh fragment #### while [ $FILES -gt 0 ] do echo "$FILES" ((FILES -= 1)) # or ((FILES = $FILES - 1)) done #### ksh fragment #### ...Kris -- Kristopher Stephens, | (408-746-6047) | krs@uts.amdahl.com | KC6DFS Amdahl Corporation | | | [The opinions expressed above are mine, solely, and do not ] [necessarily reflect the opinions or policies of Amdahl Corp. ]
robtu@itx.isc.com (Rob Tulloh) (04/06/91)
miquels@maestro.htsa.aha.nl (Miquel van Smoorenburg) writes: >In article <3693@ux.acs.umn.edu> edh@ux.acs.umn.edu (Merlinus Ambrosius) writes: >>In sh, I'd like to do something like a BASIC for loop. Say I have $FILES >>set to some number, and I'd like to go through a loop $FILES times. Can >>this be done in sh? >POSIX states that sh(1) should be able to evaluate expressions, >so you can do something like >while [ $FILES != 0 ] >do > echo -n '* ' > FILES=$[$FILES - 1] >done >But I haven't seen a sh anywhere that is already capable of doing this >(not even the one I am writing myself for Minix... yet.). >Maybe somebody knows if a new ksh can do this? In the version of ksh running on the RS/6000, the following is possible: typeset -i FILES=10 while [ $i -gt 0 ] ; do # body of loop FILES=FILES-1 done or the following: typeset -i FILES=10 while ((i > 0)) ; do # body of loop FILES=FILES-1 done or if you want to be more specific: typeset -i FILES=10 while ((i > 0)) ; do # body of loop let FILES=FILES-1 done The typeset -i forces FILES to be interpreted as an integer and allows you to forgo the use of $var and the let syntax. let is a shell builtin which uses (( and )) as shorthand much the same way test uses [ and ]. Rob Tulloh -- INTERACTIVE Systems Corp. Tel: (512) 343 0376 Ext. 116 9442 Capital of Texas Hwy. North Fax: (512) 343 0376 Ext. 161 (not a typo!) Arboretum Plaza One, Suite 700 Net: robertt@isc.com (polled daily) Austin, Texas 78759 GEnie: R.TULLOH (polled monthly)
ask@cbnews.att.com (Arthur S. Kamlet) (04/06/91)
In article <robtu.670879801@mexia> robtu@itx.isc.com (Rob Tulloh) writes: >In the version of ksh running on the RS/6000, the following is possible: > >typeset -i FILES=10 >while [ $i -gt 0 ] ; do > # body of loop > FILES=FILES-1 >done > >The typeset -i forces FILES to be interpreted as an integer and allows >you to forgo the use of $var and the let syntax. In fact, my ksh comes with an exported alias for typeset -i named "integer" So I can say: integer FILES=10 -- Art Kamlet a_s_kamlet@att.com AT&T Bell Laboratories, Columbus
rich@pencil.cs.missouri.edu (Rich Winkel) (04/06/91)
jik@athena.mit.edu (Jonathan I. Kamens) writes: ]In article <3693@ux.acs.umn.edu>, edh@ux.acs.umn.edu (Merlinus Ambrosius) writes: ]|> In sh, I'd like to do something like a BASIC for loop. Say I have $FILES ]|> set to some number, and I'd like to go through a loop $FILES times. Can ]|> this be done in sh? ]Yes. The trick is getting from the number to that many items that you can put ]into a for loop. Something like this ] FILES=10 ] for i in `jot $FILES`; do ] echo -n "*" ] done; echo "" ]will print ten asterisks and then a newline, if your echo supports "-n" ]and you have "jot". If you don't have "jot", you can get it from ]/help/dist on lilac.berkeley.edu. .... How about this variation for those who don't have jot: FILES=10 for i in `head -$FILES /usr/dict/words` echo -n "*" done I guess someone's going to tell me now that 'head' isn't standard unix? Rich
chet@odin.INS.CWRU.Edu (Chet Ramey) (04/07/91)
In article <2816@maestro.htsa.aha.nl> miquels@maestro.htsa.aha.nl (Miquel van Smoorenburg) writes:
$ POSIX states that sh(1) should be able to evaluate expressions,
$ so you can do something like
$ while [ $FILES != 0 ]
$ do
$ echo -n '* '
$ FILES=$[$FILES - 1]
$ done
$
$ But I haven't seen a sh anywhere that is already capable of doing this
Bash can do this, at least as of version 1.07.
Chet
--
Chet Ramey Internet: chet@po.CWRU.Edu
Case Western Reserve University NeXT Mail: chet@macbeth.INS.CWRU.Edu
``Now, somehow we've brought our sins back physically -- and they're pissed.''
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/07/91)
In article <rich.670890780@pencil> rich@pencil.cs.missouri.edu (Rich Winkel) writes: > for i in `head -$FILES /usr/dict/words` > echo -n "*" > done for i in `yes | head -$FILES` echo -n "*" done But for this I'd probably just write yes '*' | head -$FILES | tr -d ' ' And let's not forget the poor man's count script: #!/bin/sh ( echo $1 ; yes | head -$2 | sed 's/y/p1+/' ) | dc $1 is the starting number, $2 how many numbers to produce. It even works for floating-point---try count 3.14159 10. ---Dan
ronald@robobar.co.uk (Ronald S H Khoo) (04/07/91)
rich@pencil.cs.missouri.edu (Rich Winkel) writes: > FILES=10 > for i in `head -$FILES /usr/dict/words` Hee hee. Neat hack. I got a feeling that my boss would be very unhappy if I used that in production code though :-) But I like it. > I guess someone's going to tell me now that 'head' isn't standard unix? Yes, but unless you're head'ing more than one file, sed <n>q is the same as head -n, so you could have avoided the use of that disclaimer, had you said: for i in `sed ${FILES}q /usr/dict/words` Also, if no shell variables are involved, sed 10q is less to type than head -10 :-) -- Ronald Khoo <ronald@robobar.co.uk> +44 81 991 1142 (O) +44 71 229 7741 (H)
dattier@vpnet.chi.il.us (David W. Tamkin) (04/08/91)
rich@pencil.cs.missouri.edu (Rich Winkel) wrote in <rich.670890780@pencil>:
| I guess someone's going to tell me now that 'head' isn't standard unix?
It's standard in BSD but don't look for it in System V.
David Tamkin PO Box 7002 Des Plaines IL 60018-7002 dattier@vpnet.chi.il.us
GEnie:D.W.TAMKIN CIS:73720,1570 MCIMail:426-1818 708 518 6769 312 693 0591
"Parker Lewis Can't Lose" mailing list --
relay: flamingo-request@esd.sgi.com digest: flamingo-request@ddsw1.mcs.com
kiyun@mirror.tmc.com (KiYun Roe) (04/08/91)
In article <27850:Apr700:08:2591@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >And let's not forget the poor man's count script: > > #!/bin/sh > ( echo $1 ; yes | head -$2 | sed 's/y/p1+/' ) | dc I like this! I've been looking for a simple way to do this. I didn't realize that there was a command like yes. Is it BSD, System V, or both? Anyway, I don't think you need to bring sed into the pipe: #!/bin/sh ( echo $1 ; yes p1+ | head -$2 ) | dc -- ---- KiYun Roe kiyun@mirror.TMC.COM Mirror Systems 2067 Massachusetts Avenue Cambridge, MA 02140 Telephone: 617-661-0777
pfinkel@cbnewsb.cb.att.com (paul.d.finkel) (04/10/91)
In article <3693@ux.acs.umn.edu> edh@ux.acs.umn.edu (Merlinus Ambrosius) writes: >In sh, I'd like to do something like a BASIC for loop. Say I have $FILES >set to some number, and I'd like to go through a loop $FILES times. Can >this be done in sh? > >Thanks! > --eric Sure! count=0 while $count -lt $files do : count=`expr $count + 1` done I think this will do it! -- Family motto: Semper ubi, sub ubi. mail: attmail!pfinkel "My name is Fink, whaddaya think, I press pants for nothing?" (Punch line to corny joke that my father always told!)
pfinkel@cbnewsb.cb.att.com (paul.d.finkel) (04/10/91)
In article <1991Apr9.185256.18650@cbfsb.att.com> pfinkel@cbnewsb.cb.att.com (paul.d.finkel) writes: >In article <3693@ux.acs.umn.edu> edh@ux.acs.umn.edu (Merlinus Ambrosius) writes: >>In sh, I'd like to do something like a BASIC for loop. Say I have $FILES >>set to some number, and I'd like to go through a loop $FILES times. Can >>this be done in sh? >> >>Thanks! >> --eric >Sure! > > count=0 > while $count -lt $files > do > : > count=`expr $count + 1` > done >I think this will do it! Escuse mio, per favor. You need brackets around your test statetment: while [ $count -lt $files ] -- Family motto: Semper ubi, sub ubi. mail: attmail!pfinkel "My name is Fink, whaddaya think, I press pants for nothing?" (Punch line to corny joke that my father always told!)
stuart@amc.com (Stuart Poulin) (04/11/91)
In article <54239@mirror.tmc.com> kiyun@mirror.UUCP (KiYun Roe) writes: >In article <27850:Apr700:08:2591@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >>And let's not forget the poor man's count script: >> >> #!/bin/sh >> ( echo $1 ; yes | head -$2 | sed 's/y/p1+/' ) | dc > >I like this! I've been looking for a simple way to do this. I didn't >realize that there was a command like yes. Is it BSD, System V, or >both? Anyway, I don't think you need to bring sed into the pipe: > > #!/bin/sh > ( echo $1 ; yes p1+ | head -$2 ) | dc >-- >---- Hey! cool idea. How about using bc and adding a step argument: # print range from $1 to $2 step $3 echo " for ( i = $1; i <= $2 ; i += $3 ) { i } " | bc You can even step fractional steps - try it: 1 10 .1 And you can even swap "<=" around to count down. Wow! Stuart Poulin DNS: stuart@amc.com Applied Microsystems Corporation UUCP: amc-gw!stuart Redmond, Washington 98073 Dial: 800-ASK-4AMC,206-882-2000
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/12/91)
In article <1991Apr10.212216.24238@amc.com> stuart@tfatf.amc.com (Stuart Poulin) writes: > In article <54239@mirror.tmc.com> kiyun@mirror.UUCP (KiYun Roe) writes: > >I like this! I've been looking for a simple way to do this. I didn't > >realize that there was a command like yes. Is it BSD, System V, or > >both? I believe it appeared in v7, but I'm not sure how portable the argument is. > Hey! cool idea. How about using bc and adding a step argument: No need for bc. Step can be positive or negative here. #!/bin/sh # pmcount start [ num [ step ] ], num default 10, step default 1 step=`echo ${3-1} | sed 's/-/_/g'` ( echo $1 ; yes | head -${2-10} | sed 's/y/p'$step'+/' ) | dc I suppose the yes and head could be replaced by echo and a more complex sed script. ---Dan
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/13/91)
In article <13418:Apr1203:39:4891@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: > In article <1991Apr10.212216.24238@amc.com> stuart@tfatf.amc.com (Stuart Poulin) writes: > > In article <54239@mirror.tmc.com> kiyun@mirror.UUCP (KiYun Roe) writes: > > >I like this! I've been looking for a simple way to do this. I didn't > > >realize that there was a command like yes. Is it BSD, System V, or > > >both? > I believe it appeared in v7, but I'm not sure how portable the argument > is. Correction: I looked it up, and AT&T didn't have it in 1985. Oh, well. ---Dan
pfeiffer@cix.cict.fr (Daniel Pfeiffer) (04/16/91)
What I don't like about the expr example, is the number of times we need to fork, since it's not a builtin. The following, adapted from a proposal one or two months back is a bit hard to understand, (documented at the end) but should be lots quicker: $ FILES=5 $ for i in `echo "[p 1 + d $FILES!<P] sP 1 lP x" | dc` > do > echo $i > done 1 2 3 4 5 $ Someone also proposed a comparable script for awk, but, given that awk is a rather huge language, I suppose that dc is quicker. Alternately, for better readability, you might say count() { echo "[p 1 + d $1 !<P] sP 1 lP x" | dc } for i in `count 5` You can also twiddle the first 1 to change the increment, or the second 1 to change the starting point, as in the following script: #! /bin/sh if [ ! "$1" ]; then echo "usage: count number count beg end [step]">&2 exit 1 elif [ $# = 1 ]; then set 1 $1 fi # Program [ print top, increment top, duplicate, push end, pop and compare # two top values, reexecute P if not past end ] # store program as P, push beginning, load P, execute it echo "[p ${3-1} + d $2 !<P] sP $1 lP x" | dc -- -- Daniel Pfeiffer <pfeiffer@cix.cict.fr> -- Tolosa (Toulouse), Midi-Pyrenees, Europe <pfeiffer@irit.fr> -- "Beware - polyglot esperantist" <pfeiffer@frcict81.bitnet> -- N _---_ / \ NEWS, it goes around the world. W (-------) E (sorry, my bitmap doesn't have a world-class resolution) \_ _/ ---