[comp.unix.questions] Line at a time scripts in csh

posert@bonnie.ics.uci.edu (Bob Posert) (01/14/89)

I have a file with two words on each line, and want to
process them in a shell script, but can't figure out
how to get *the entire line* into a variable.

I tried:
	foreach i (`cat file`)
	#misc processing
	end
but i was set to each word, not line.

Then I tried the same thing, but adding quotes at the beginning and
end of every line in the input file.  Basically the same thing happened,
even though from the prompt,
	foreach i ("One Two")
	echo $i
	end
echoed the words on the same line.

Any ideas?  Thanks in advance.
--Bob
--
Bob Posert
I'm: posert@bonnie.ics.uci.edu or {sdcsvax|ucbvax}!ucivax!bonnie!posert 

maart@cs.vu.nl (Maarten Litmaath) (01/14/89)

posert@bonnie.ics.uci.edu (Bob Posert) writes:
\I have a file with two words on each line, and want to
\process them in a shell script, but can't figure out
\how to get *the entire line* into a variable.
\I tried:
\	foreach i (`cat file`)
\	#misc processing
\	end
\but i was set to each word, not line.

foreach i ("`cat file`")	# create 1 string
	..."$i"...		# avoid * and friends getting expanded
end
-- 
Lee Harvey Oswald was a patsy.        |Maarten Litmaath @ VU Amsterdam:
                       Or a superman. |maart@cs.vu.nl, mcvax!botter!maart

marquez@pnet01.cts.com (Dan Castro) (01/16/89)

maart@cs.vu.nl (Maarten Litmaath) writes:
>posert@bonnie.ics.uci.edu (Bob Posert) writes:
>>I have a file with two words on each line, and want to
>>process them in a shell script, but can't figure out
>>how to get *the entire line* into a variable.
>>I tried:
>>       foreach i (`cat file`)
>>       #misc processing
>>       end
>>but i was set to each word, not line.
>
>foreach i ("`cat file`")        # create 1 string
>        ..."$i"...              # avoid * and friends getting expanded
>end

I had been trying to do the same sort of thing and came up with a
different method. The script shown above didn't work on my system.
(Microport V/AT 286 2.3) The following did work for both the Bourne
and c shells...

---------------------cut here-------cut here--------------------
# expander
#
# expander processes the "datafile" a line at a time using the
# "read" function. The resulting output is the original line
# followed by the first two (white space separated) fields in
# reverse order, on the same line.
#
expander()
{
while read line
do
  one=`echo "$line" | awk ' { print $1 } '`
  two=`echo "$line" | awk ' { print $2 } '`
  echo "$line: $two $one"
done
}

# main: shell execution starts here
  cat datafile | expander

--------------------cut here---------cut here-------------------

UUCP: {nosc ucsd hplabs!hp-sdd}!crash!pnet01!marquez
ARPA: crash!pnet01!marquez@nosc.mil
INET: marquez@pnet01.cts.com

geoff@warwick.UUCP (Geoff Rimmer) (01/17/89)

In article <4116@paris.ics.uci.edu> posert@bonnie.ics.uci.edu (Bob Posert) writes:
>
>I have a file with two words on each line, and want to
>process them in a shell script, but can't figure out
>how to get *the entire line* into a variable.
>
>I tried:
>	foreach i (`cat file`)
>	#misc processing
>	end
>but i was set to each word, not line.
>

If you do

	foreach i ("`cat file`")
	#misc processing
	end

you will get the whole line.  However, when I tried this just now, I
realised that if there are any wild cards (?,*,[,]) then it gives the
strange error message 

	end: No match

when it gets to the line containing the ? or whatever.  Can anyone
explan this one?

>Then I tried the same thing, but adding quotes at the beginning and
>end of every line in the input file.  Basically the same thing happened,
>even though from the prompt,
>	foreach i ("One Two")
>	echo $i
>	end
>echoed the words on the same line.

I suppose when csh interprets the output of the `...` , it ignores the
quotes, but I have no idea why it should do so!!

Way back in my first year (and most of the second) I was there slaving
away at sorting out which quotes to use in csh/sh and when or not to
use a backslash etc, and I got so fed up, that I haven't written any
scripts since (except for the simplest type) and now everything is in C.  
OK, it takes a lot longer to write, but it's a lot faster, it's more
reliable, and a lot more powerful!

>   Bob Posert
>   I'm: posert@bonnie.ics.uci.edu or {sdcsvax|ucbvax}!ucivax!bonnie!posert 

Geoff


	------------------------------------------------------------
	Geoff Rimmer, Computer Science, Warwick University, England.
			geoff@uk.ac.warwick.emerald

	"It just goes to show, if you want something doing properly,
	it's best not to drink 16 pints of lager beforehand."
		- Filthy Rich and Catflap, 1986.
	------------------------------------------------------------

posert@bonnie.ics.uci.edu (Bob Posert) (01/17/89)

Thanks to everyone who sent me the solution:
	foreach i ("`cat file`")
		#whatever
	end

And special thanks go to Mike Khaw, who correctly pointed out
that you lose leading whitespace and lines that are only whitespace 
by doing the above.  Fortunately, it didn't matter for my application.

--Bob
--
Bob Posert
I'm: posert@bonnie.ics.uci.edu or {sdcsvax|ucbvax}!ucivax!bonnie!posert 

lukas@ihlpf.ATT.COM (00771g-Lukas) (01/18/89)

In article <4116@paris.ics.uci.edu> posert@bonnie.ics.uci.edu (Bob Posert) writes:
>
>I have a file with two words on each line, and want to
>process them in a shell script, but can't figure out
>how to get *the entire line* into a variable.

Nobody mentioned IFS, so I thought Id through my $.02 in. The following
will I think solve the problem:

	ifs_def=$IFS
	ifs_nl="\
	"
	while read in; do
		echo "$in"
		# other stuff
	IFS="$ifs_nl"
	done <t.in
	IFS="$ifs_def"

Now, Im not sure why the IFS change surrounds the redirection (my first
impulse was to have it surround the "read"), however, it works
correctly (empirically). It handles leading white space and special
characters correctly. It has the additional benefit of
working with sh, ksh, and csh.
-- 

	John Lukas
	att!ihlpf!lukas
	312-510-6290

guy@auspex.UUCP (Guy Harris) (01/20/89)

>It has the additional benefit of working with sh, ksh, and csh.

"csh" has an IFS variable that you can set?  News to me....

dberg@cod.NOSC.MIL (David I. Berg) (01/24/89)

In article <909@ubu.warwick.UUCP>, geoff@warwick.UUCP (Geoff Rimmer) writes:
> In article <4116@paris.ics.uci.edu> posert@bonnie.ics.uci.edu (Bob Posert) writes:

> >	foreach i (`cat file`)
> >	#misc processing
> >	end
> >but i was set to each word, not line.

When I encountered the same problem I used an oscillating soft switch to
keep track of which word to which I was was pointing.  It's a kludge, but
it works.

> However, when I tried this just now, I realised that if there are any wild 
> cards (?,*,[,]) then it gives the strange error message "end: No match"

Set the environment variable "nonomatch" to eliminate no matches.

-- 
David I. Berg (dberg@nosc.mil)
GENISYS Information Systems, Inc., 4250 Pacific Hwy #118, San Diego, CA 92110
MILNET: dberg@nosc.mil
UUCP:   {akgua decvax dcdwest ucbvax}!sdcsvax!noscvax!dberg

lukas@ihlpf.ATT.COM (00771g-Lukas) (01/24/89)

In article <872@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
>>It has the additional benefit of working with sh, ksh, and csh.
>
>"csh" has an IFS variable that you can set?  News to me....

In the words of the great philosopher, Mr. Peevee, "Well, now, I dont
know about that." Im not a csh user, so I dont know. I just wrote
the script as given, and tried it with sh, ksh, and csh, and it
worked for all three.
-- 

	John Lukas
	att!ihlpf!lukas
	312-510-6290

guy@auspex.UUCP (Guy Harris) (01/26/89)

>I just wrote the script as given, and tried it with sh, ksh, and csh, and it
>worked for all three.

The "csh" on your system must be something other than the C shell, then,
because the C shell is quite different from the Bourne shell, and it
complained as soon as it saw

	ifs_def=$IFS

because it said that IFS was an undefined variable; when I defined it,
it gave

	ifs_def=: Command not found.

instead.  The way you set shell variables is different in the C shell,
so it didn't like "ifs_def=$IFS".

Most non-trivial Bourne shell scripts probably don't work at all if you
run them under the C shell. 

(Obligatory clarification, to ward off "Wrong! See, here's *my* trick
for doing that" postings: Most non-trivial Bourne shell scripts probably
don't work at all under the C shell unless you do a Larry Wall-style
"ooops, wrong shell, I'll feed myself to 'sh'" trick, or have some other
trick, perhaps along the lines of those programs that represented valid
C, Pascal, and FORTRAN source through clever use of the three languages'
comment conventions.)

lukas@ihlpf.ATT.COM (00771g-Lukas) (01/26/89)

In article <891@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
>>I just wrote the script as given, and tried it with sh, ksh, and csh, and it
>>worked for all three.
>
>The "csh" on your system must be something other than the C shell, then,
>because the C shell is quite different from the Bourne shell, and it
>complained as soon as it saw
>
>	ifs_def=$IFS

No, it turns out that my "csh" is in fact the C shell, but I must have
been doing something wrong. Im hoping that you can enlighten me. I made
the script executable, then issued it from csh, vis:

	lpf lukas> csh
	% foo
	# correct! results of foo here
	% exit
	lpf lukas>

However, when I issued:

	lpf lukas> csh foo

It failed with messages like you suggested. So, I threw in a
"ps" into "foo", and found that "csh" forked a "sh" process to actually
run "foo", and that is why it worked. I guess I didnt expect that.
Why was a "sh" child produced, instead of another "csh" (or, anyway,
a "ksh", which is my login shell, and the value of SHELL)? Any ideas?
Parenthetically, I did the same sort of thing with "ksh" instead of "csh",
and another "ksh" (NOT a "sh") was forked to run the "ps".

As a side issue, is there any way to know, from within a process, what
the "current" shell is? It would seem to me that an environment variable
would be best. Something like "CURR_SHELL", that would have "sh", "ksh",
etc., or somesuch. I suggested some such to David Korn for the ksh, but
he did not see the need. I suppose that I could use the output of "ps",
then track back child to parent until I got to a shell, but that seems
like an awful lot of work. Any ideas on this?
-- 

	John Lukas
	att!ihlpf!lukas
	312-510-6290

gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/27/89)

In article <7449@ihlpf.ATT.COM> lukas@ihlpf.UUCP (00771g-Lukas,J.) writes:
>It failed with messages like you suggested. So, I threw in a
>"ps" into "foo", and found that "csh" forked a "sh" process to actually
>run "foo", and that is why it worked. I guess I didnt expect that.
>Why was a "sh" child produced, instead of another "csh" (or, anyway,
>a "ksh", which is my login shell, and the value of SHELL)? Any ideas?
>Parenthetically, I did the same sort of thing with "ksh" instead of "csh",
>and another "ksh" (NOT a "sh") was forked to run the "ps".

The implementors of your csh should be congratulated for getting this
right (for a change).  csh is supposed to feed scripts to a Bourne shell.
The only exception would be if your kernel doesn't support #! execs but
(ALL) your shells are expected to take care of this, in which case the
#! line should be interpreted and the appropriate processor run to handle
the script.

The Korn shell is supposedly upward-compatible with the Bourne shell, so
it is able to handle scripts directly instead of invoking a separate shell.

guy@auspex.UUCP (Guy Harris) (01/27/89)

>Why was a "sh" child produced, instead of another "csh" (or, anyway,
>a "ksh", which is my login shell, and the value of SHELL)? Any ideas?

A long time ago, in a galaxy far, far away (well, I dunno, how far is
Berkeley, CA from Napierville, IL?), Bill Joy wrote a shell for either
V6 or V7 UNIX.  At least when run under V7, it wasn't compatible with
the existing UNIX shell; since people wanted to use the C shell as their
login shell, and possibly write C shell scripts, but still be able to
run Bourne shell scripts as well, both the Bourne and C shells were
hacked up to try to recognize each other's scripts and run the other
shell if they recognized a "foreign" script.

The versions of the Bourne and C shells that I'm familar with that do
this check the first character of the script; the C shell assumes that a
script beginning with ":" is a Bourne shell script, and the Bourne shell
assumes that a script beginning with "#" is a C-shell script.  (":" was
a no-op command used as a sort of comment in the Bourne shell; the C
shell accepted comments beginning with "#" which were *real* comments
not scanned by its parser, so ":" tended not to be used in C shell
scripts, and since the Bourne shell did not originally have "#"
comments, "#" tended not to be used in Bourne shell scripts.)

(Subsequently, Berkeley added the "#!" mechanism - suggested, I'm told,
by Dennis Ritchie - that allows "exec" system calls to "directly"
execute shell scripts; the kernel recognizes "#!" as the first two
characters of a file it's told to execute, and sucks a pathname from the
first line of the file and runs the program with that pathname, handing
it the pathname of the file it was originally told to execute as an
argument.  This obviates the need for the Bourne/C shell hacks, and just
in time - more recent Bourne shells support "#" comments, so you can't
validly use "#" as the first character as the deciding factor any more.)

>Parenthetically, I did the same sort of thing with "ksh" instead of "csh",
>and another "ksh" (NOT a "sh") was forked to run the "ps".

Yup, "ksh" basically thinks of itself as the only shell in the world (as
did the original Bourne shell), and if it tries to "exec" a program and
fails because it's not an executable image, it kicks off another "ksh"
to run it.  ("#!" allows you to mark shells as Bourne, C, or Korn shell
scripts - or as "awk" scripts, or....)

sar@datcon.UUCP (Simon A Reap) (01/27/89)

In article <7372@ihlpf.ATT.COM> lukas@ihlpf.UUCP (00771g-Lukas,J.) writes:
>..............    I just wrote
>the script as given, and tried it with sh, ksh, and csh, and it
>worked for all three.

Ah, but don't all of these shells (and others) run scripts via the
Bourne shell (except for the dodgy and almost-undocumented fudge of
having the first line start with a '#' or '#!/bin/csh etc etc to force
use of the C shell.  How many of us *haven't* been caught by this,
prettifying a working shell script by adding header comments, then
finding it no longer works as the Bourne shell constructs get munged by
the wonderful Cshell :-( )
-- 
Enjoy,
yerluvinunclesimon             Opinions are mine - my cat has her own ideas
Reach me at sar@datcon.co.uk, or ...!mcvax!ukc!pyrltd!datcon!sar

greywolf@unisoft.UUCP (The Grey Wolf) (01/28/89)

In article <9511@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <7449@ihlpf.ATT.COM> lukas@ihlpf.UUCP (00771g-Lukas,J.) writes:
>> [ when he typed "csh foo", foo was run with sh instead ]
>
>The implementors of your csh should be congratulated for getting this
>right (for a change).  csh is supposed to feed scripts to a Bourne shell.

Where are you getting your documentation, Doug?  Since when, if you type

% csh foo

does it feed "foo" to the Bourne shell?  This is not correct, and certainly
not normal!  If I feed a script to csh, csh had better run it, since that
was my intention.  Otherwise, it would be rather redundant, what?

>The only exception would be if your kernel doesn't support #! execs but
>(ALL) your shells are expected to take care of this, in which case the
>#! line should be interpreted and the appropriate processor run to handle
>the script.

System V, release 3 does not support #! execs.  I know, because I *work*
with them all bloody day.  #! is constantly ignored.

---
Roan Anderson, Software Engineer, UniSoft Corp.
6121 Hollis St. Emeryville, CA  94608
My opinions are my own and not those of UniSoft Corporation.
If I want your opinion, I'll give it to you.
-- 
...TheysaidDoyouseethebiggreenglowinthedarkhouseuponthehill?andIsaidYesIseethebiggreenglowinthedarkhouseuponthehillTheresabigdarkforestbetweenmeandthebiggreenglowinthedarkhouseuponthehillandalittleoldladyonaHoovervacuumcleanersayingIllgetyoumyprettyandyourlittledogTototoo
I don't even *HAVE* a dog Toto...

gwyn@smoke.BRL.MIL (Doug Gwyn ) (01/28/89)

In article <1837@unisoft.UUCP> greywolf@unisoft.UUCP (The Grey Wolf) writes:
>In article <9511@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>>In article <7449@ihlpf.ATT.COM> lukas@ihlpf.UUCP (00771g-Lukas,J.) writes:
>>> [ when he typed "csh foo", foo was run with sh instead ]

No, that wasn't what he said!  He was running interactively under csh,
and typing "foo" invoked an "sh" to interpret it.

>System V, release 3 does not support #! execs.

I never said it did.