[comp.unix.questions] Some csh how-to, please

pklammer@pikes.Colorado.EDU (Peter Klammer) (03/28/89)

Could someone please tell me how to read a file line at a time
into the C shell?  Better yet, can you refer me to any good C-shell
text.  So far my references are mere appendices in UNIX manuals with,
"here's a table of equivalent Bourne and C shell commands..."; next to
'read' in the Bourne column is a blank in the C shell column.  THANKS!

dje@imokay.dec.com ( SVS) (03/28/89)

pklammer@pikes.Colorado.EDU (Peter Klammer) writes:
> Could someone please tell me how to read a file line at a time
> into the C shell?  Better yet, can you refer me to any good C-shell
> text.  So far my references are mere appendices in UNIX manuals with,
> "here's a table of equivalent Bourne and C shell commands..."; next to
> 'read' in the Bourne column is a blank in the C shell column.  THANKS!

Check the csh meta-variable $<, which (and I quote from man):

Substitutes a line from the standard input, with no further interpretation
thereafter.  It can be used to read from the keyboard in a shell script.

----
David Ellis
Digital Equipment Corporation -- BXB1-1/D03 
85 Swanson Road, Boxboro MA 01719 -- (617) 264-5073
Usenet:  {ucbvax,allegra,decvax}!decwrl!ultra.dec.com!ellis
ARPA:    ellis%ultra.dec@decwrl.dec.com

white@white.cs.unc.edu (Brian T. White) (03/29/89)

In article <2127@pikes.Colorado.EDU>, pklammer@pikes.Colorado.EDU (Peter Klammer) writes:
> Could someone please tell me how to read a file line at a time
> into the C shell?  Better yet, can you refer me to any good C-shell
> text.  

Try "The UNIX C Shell Field Guide" by Anderson and Anderson.  To read
a file one line at a time, try

foreach p ( "`cat file`" )
	set line=`echo $p`
	(commands acting on $line)
end

karish@forel.stanford.edu (Chuck Karish) (03/29/89)

In article <7467@thorin.cs.unc.edu> white@white.cs.unc.edu
(Brian T. White) wrote:
>In article <2127@pikes.Colorado.EDU>, pklammer@pikes.Colorado.EDU
(Peter Klammer) writes:
>> Could someone please tell me how to read a file line at a time
>> into the C shell?

>To read a file one line at a time, try
>
>foreach p ( "`cat file`" )
>	set line=`echo $p`
>	(commands acting on $line)
>end

This fails if 'file' is longer than the allowable length for an
input line.

The following script fragment reads standard input up to a magic cookie
(I don't know how to detect EOF in csh):

#! /bin/csh

set fie=1
while ( "$fie" != "@" )
	set fie=$<
	echo A $fie
end

If this is in an executable file called 'foo', the command would look like

	(cat file; echo "@") | foo

Note that, in csh, it's not possible to pipe to a loop inside the
script, and the script doesn't get a return value from the 'set' command.
An sh script to do this job would look like

cat file |
while read fie
do
	echo A $fie
done

No magic cookies needed; 'read fie' fails at EOF.
A pipe or redirect after 'done' receives the entire output of the loop.

csh is OK as an interactive command line interpreter.  As a programming
language, it's not so hot.   My advice would be to get a copy of
Kernighan and Pike, and use sh instead.

	Chuck Karish	hplabs!hpda!mindcrf!karish	(415) 493-7277
			karish@forel.stanford.edu

bollella@ra.cs.unc.edu (Gregory Bollella) (03/29/89)

In article <7467@thorin.cs.unc.edu> white@white.cs.unc.edu (Brian T. White) writes:
>In article <2127@pikes.Colorado.EDU>, pklammer@pikes.Colorado.EDU (Peter Klammer) writes:
>> Could someone please tell me how to read a file line at a time
>> into the C shell?  Better yet, can you refer me to any good C-shell
>> text.  
>
>Try "The UNIX C Shell Field Guide" by Anderson and Anderson.  To read
>a file one line at a time, try
>
>foreach p ( "`cat file`" )
>	set line=`echo $p`
>	(commands acting on $line)
>end

I tried the above on a large file and it did not work.  csh reported
       Too many words from ``.
The file was 118583 bytes.  Does anybody have any ideas on how to 
get around this limit and still get one line at a time?

Gregory Bolella                 bollella@cs.unc.edu
Department of Computer Science
CB# 3175 Sitterson Hall
University of North Carolina
Chapel Hill, NC 27599-3175

sethr@cunixc.cc.columbia.edu (Seth Robertson) (03/30/89)

In article <7485@thorin.cs.unc.edu> bollella@ra.UUCP (Gregory Bollella) writes:
>>In article <2127@pikes.Colorado.EDU>, pklammer@pikes.Colorado.EDU (Peter Klammer) writes:
>>> Could someone please tell me how to read a file line at a time
>>> into the C shell?  Better yet, can you refer me to any good C-shell
>>> text.  
>> [Method deleted]
>I tried the above on a large file and it did not work.  csh reported
>       Too many words from ``.
>The file was 118583 bytes.  Does anybody have any ideas on how to 
>get around this limit and still get one line at a time?

I don't know how to do it in csh, but the method that works for (k)sh is:

#! /bin/sh
exec 3<&0 < /usr/local/lib/ctrsuns
while read test
do
echo $test
rsh $test -n "$1"
done
exec 0<&3 3<&-

This gives the error missing name for redirect.  You might
be able to fool around with it and get it working...

					-Seth
					 seth@ctr.columbia.edu

merlyn@intelob.intel.com (Randal L. Schwartz @ Stonehenge) (03/31/89)

In article <1175@Portia.Stanford.EDU>, karish@forel (Chuck Karish) writes:
| [ a lot of stuff deleted]
| An sh script to do this job would look like
| 
| cat file |
| while read fie
| do
| 	echo A $fie
| done
| 
| No magic cookies needed; 'read fie' fails at EOF.
| A pipe or redirect after 'done' receives the entire output of the loop.
| 
| csh is OK as an interactive command line interpreter.  As a programming
| language, it's not so hot.   My advice would be to get a copy of
| Kernighan and Pike, and use sh instead.

Why do people use 'cat' at every opportunity?  Maybe that's why
they sell so many multiprocessor machines? :-) :-)

Simpler:

	while read fie
	do
		something with $fie
	done <file

no additional processes.

I agree about sh vs csh.  But I won't get started in *that* religious
war.  Get ksh... the best of both worlds (hee hee)...

A unix wizard (or one that plays one on TV...),
-- 
/     Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095        \
|        on contract to BiiN (for now :-) Hillsboro, Oregon, USA.             |
|<@intel-iwarp.arpa:merlyn@intelob.intel.com> ...!uunet!tektronix!biin!merlyn |
\     Cute quote: "Welcome to Oregon... home of the California Raisins!"      /

dce@stan.UUCP (David Elliott) (04/03/89)

In article <4258@omepd.UUCP> merlyn@intelob.intel.com (Randal L. Schwartz @ Stonehenge) writes:
>Why do people use 'cat' at every opportunity?  Maybe that's why
>they sell so many multiprocessor machines? :-) :-)

>Simpler:
>
>	while read fie
>	do
>		something with $fie
>	done <file
>
>no additional processes.

I agree with you in principle.  It is silly to use cat and a pipe
when simple redirection will work.

In practice, you are unfortunately wrong.  The best that redirection
gives you is one less exec.  Current "standard" versions of sh (in
other words, most sh's other than ksh) fork when redirection is done
on a loop.

Try this script:

	#!/bin/sh

	PLACE=out
	while read line
	do
		PLACE=in
	done < /etc/group

	echo "PLACE is $PLACE"
	exit 0

The output on my system (SunOS 4.0.1) is

	PLACE is out

A better solution is

	exec 3<&0 <file
	while read fie
	do
		something with $fie
	done
	exec 0<&3

This really doesn't take any additional processes, and it leaves the
file descriptor for standard input available in fd 3 in case you need
it (it's bad, though typical, practice to redirect from /dev/tty, which
may not be correct).

-- 
David Elliott		...!pyramid!boulder!stan!dce
"Splish splash, I was rakin' in the cash"  -- Eno

dgk@ulysses.homer.nj.att.com (David Korn[drew]) (04/05/89)

In article <718@salgado.stan.UUCP>, dce@stan.UUCP (David Elliott) writes:
> In article <4258@omepd.UUCP> merlyn@intelob.intel.com (Randal L. Schwartz @ Stonehenge) writes:
> >Why do people use 'cat' at every opportunity?  Maybe that's why
> >they sell so many multiprocessor machines? :-) :-)
> 
> >Simpler:
> >
> >	while read fie
> >	do
> >		something with $fie
> >	done <file
> >
> >no additional processes.
> 
> 
> In practice, you are unfortunately wrong.  The best that redirection
> gives you is one less exec.  Current "standard" versions of sh (in
> other words, most sh's other than ksh) fork when redirection is done
> on a loop.
> 

The big problem with
	cat file | while read ...

is that it runs about 1/10th the speed of the redirection loop.
The reason is that the shell (sh and/or ksh) have to read one
character at a time when reading from a pipe.  The reason for
reading one character at a time is to make scripts like
	cat file | ( read line;cat)
behead only a single line.

Unfortunately there is not way to seek back on a pipe.  Nor is
there an ioctl() to specify line buffering.  Thus, single characters
reads are used.  This is not the case when you specify redirection.

I hope that someone will add a stream discipline that will cause
pipes to use a line buffering protocol.  Until such time, scripts
would do better to use a temporary file rather than piping to
a while read loop.