[comp.unix.questions] Cshell question: taking wordlists as a single string

andy@syma.sussex.ac.uk (Andy Clews) (08/14/90)

I have a Csh script called "whatnews" which takes words as arguments and
searches the file /usr/lib/news/newsgroups for lines containing any one
of those words, the requirement being to show users what newsgroups are
there that may be something to do with the searched word.  It is not
case sensitive (i.e.  it uses fgrep -i)

	whatnews biology

"whatnews" then proceeds to show me all lines in /usr/lib/news/newgroups
that contain the string "biology".  If several words are supplied as a
list, whatnews searches the file for each of these words.  The
difficulty arises because I want to do (for example)

	whatnews "bug reports"

where the intended effect is to search out all lines containing the
string "bug reports". At the moment it splits this up into "bug" and
"reports" and does two searches. This is because the script contains a
      foreach i ($*)
loop for repeated searches.  Quoting (single or double) doesn't help.

Basically, then, can Cshell cope with word-lists as single arguments, or
must I write a C program to do the job (or try sh or ksh?)

No joy as yet with TFM. Any help appreciated; email probably best. I
will summarise if possible. Thanks for listening.



-- 
Andy Clews, Computing Service, Univ. of Sussex, Brighton BN1 9QN, England
JANET: andy@syma.sussex.ac.uk   BITNET: andy%syma.sussex.ac.uk@uk.ac

merlyn@iwarp.intel.com (Randal Schwartz) (08/16/90)

In article <3251@syma.sussex.ac.uk>, andy@syma (Andy Clews) writes:
| I have a Csh script called "whatnews" which takes words as arguments and
| searches the file /usr/lib/news/newsgroups for lines containing any one
| of those words, the requirement being to show users what newsgroups are
| there that may be something to do with the searched word.  It is not
| case sensitive (i.e.  it uses fgrep -i)
| 
| 	whatnews biology
| 
| "whatnews" then proceeds to show me all lines in /usr/lib/news/newgroups
| that contain the string "biology".  If several words are supplied as a
| list, whatnews searches the file for each of these words.  The
| difficulty arises because I want to do (for example)
| 
| 	whatnews "bug reports"
| 
| where the intended effect is to search out all lines containing the
| string "bug reports". At the moment it splits this up into "bug" and
| "reports" and does two searches. This is because the script contains a
|       foreach i ($*)
| loop for repeated searches.  Quoting (single or double) doesn't help.
| 
| Basically, then, can Cshell cope with word-lists as single arguments, or
| must I write a C program to do the job (or try sh or ksh?)
| 
| No joy as yet with TFM. Any help appreciated; email probably best. I
| will summarise if possible. Thanks for listening.

Well, you can try this Perl script:

================================================== snip snip
#!/usr/bin/perl
for (@ARGV) {
	s/\W/\\$1/g; # de-magicize
	$all .= "$_|"; # and create regular-expression
}
chop($all); # remove last "|"

open(G,"/usr/lib/news/newsgroups") || die "Cannot open newsgroups: $!";
while (<G>) {
	print if /$all/io;
}
close(G);
================================================== snip snip

Untested, but it should do the job.
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/

andy@syma.sussex.ac.uk (Andy Clews) (08/16/90)

In article <3251@syma.sussex.ac.uk>, I wrote:
> 
> Basically, then, can Cshell cope with word-lists as single arguments, or
> must I write a C program to do the job (or try sh or ksh?)
>

The solution was staring me in the face and I didn't see it until Jay Plett
sent me this solution:

% xxx "a b c" d e f
a b c
d
e
f
% cat xxx
#! /bin/csh -f

while ( $#argv )
	echo $1
	shift
end



So you must use a while loop rather than a foreach loop. So obvious now
I look at it. *sigh*

Thanks to Jay for the enlightenment.


-- 
Andy Clews, Computing Service, Univ. of Sussex, Brighton BN1 9QN, England
JANET: andy@syma.sussex.ac.uk   BITNET: andy%syma.sussex.ac.uk@uk.ac

brad@SSD.CSD.HARRIS.COM (Brad Appleton) (08/16/90)

In article <3251@syma.sussex.ac.uk> andy@syma.sussex.ac.uk (Andy Clews) writes:

In article <3251@syma.sussex.ac.uk> you write:
> The difficulty arises because I want to do (for example)
>
>	whatnews "bug reports"
>
>where the intended effect is to search out all lines containing the
>string "bug reports". At the moment it splits this up into "bug" and
>"reports" and does two searches. This is because the script contains a
>      foreach i ($*)
>loop for repeated searches.  Quoting (single or double) doesn't help.

Dont use "$*" in this case, use $argv and a while loop!
The following should work in the manner you desire:

	@ i=1
	while ( $i <= $#argv )
	  cmd "$argv[$i]"   ##dont forget those quotes!
	    .
	    .
	    .
	  @ i++
	end

Im sure there are other solutions too (probably better ones) but this
works (on my machone anyway) and should be easy to understand.
Any other solutions out there?

hope this helps!
______________________ "And miles to go before I sleep." ______________________
 Brad Appleton        brad@travis.ssd.csd.harris.com   Harris Computer Systems
                          ...!uunet!hcx1!brad          Fort Lauderdale, FL USA
~~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my company! ~~~~~~~~~~~~~~~~~~~

peter@ficc.ferranti.com (Peter da Silva) (08/17/90)

In article <3251@syma.sussex.ac.uk>, andy@syma.sussex.ac.uk (Andy Clews) writes:
> I have a Csh script called "whatnews" ...

>       foreach i ($*)

> Basically, then, can Cshell cope with word-lists as single arguments, or
> must I write a C program to do the job (or try sh or ksh?)

Try sh (not ksh, unless you don't care about portability: sh is more
universally available). By and large, csh is a poor language for writing
programs in. Sh is much better.

for i
do
	...
done

This will properly handle your quoted args.
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
peter@ferranti.com (currently not working)
peter@hackercorp.com

cudcv@warwick.ac.uk (Rob McMahon) (08/18/90)

In article <OL95_B2@xds13.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes:
>In article <3251@syma.sussex.ac.uk>, andy@syma.sussex.ac.uk (Andy Clews) writes:
>>       foreach i ($*)
>
>> Basically, then, can Cshell cope with word-lists as single arguments, or
>> must I write a C program to do the job (or try sh or ksh?)
>
>Try sh ... By and large, csh is a poor language for writing programs in. Sh
>is much better.

In fact, IMHO, handling wordlists is one area where csh beats sh hands down.
(I agree that sh is normally better for writing scripts.)  The answer is
simply

	foreach i ( $*:q )

It's very much easier to sort arguments out in csh than sh, in sh people tend
to do things like

	while [ $# -gt 0 ]; do case "$i" in
		-a) shift; aprogargs="$aprogargs $1"; shift;;
		-b) shift; bprogargs="$bprogargs $1"; shift;;
		...
	esac; done
	aprog $aprogargs | bprog $bprogargs

which of course breaks horribly if any arguments have spaces in them.  Doing
it right involves all sorts of horrible kludges with eval's and trying to get
correctly quoted single quotes in the string, while avoiding trying to quote
the single quotes that should have been there with the right number of \'s.

In csh it's just

	while ( $#argv > 0 )
		switch ( $1:q )
			case "-a":
				shift
				aprogargs = ( $aprogargs:q $1:q )
				shift
				breaksw
			case "-b":
				shift
				bprogargs = ( $bprogargs:q $1:q )
				shift
				breaksw
			...
		endsw
	end
	aprog $aprogargs:q | bprog $bprogargs:q

and there is no problem with funny arguments at all.  When I'm doing this sort
of thing I'm often tempted into using csh, in spite of its parsing problems
and less flexible traps and redirection.

I know ksh has `set -A array', but does it have an equivalent of "$@" for
arrays other than the positional paramters ?  We don't have ksh, and can't
afford to get it, but when bash gets a bit more solid I will switch to it if
it has an equivalent of csh's $array:q.

Rob
--
UUCP:   ...!mcsun!ukc!warwick!cudcv	PHONE:  +44 203 523037
JANET:  cudcv@uk.ac.warwick             INET:   cudcv@warwick.ac.uk
Rob McMahon, Computing Services, Warwick University, Coventry CV4 7AL, England

gt0178a@prism.gatech.EDU (BURNS,JIM) (08/20/90)

in article <1990Aug18.141141.24890@warwick.ac.uk>, cudcv@warwick.ac.uk (Rob McMahon) says:
> I know ksh has `set -A array', but does it have an equivalent of "$@" for
> arrays other than the positional paramters ?  We don't have ksh, and can't
> afford to get it, but when bash gets a bit more solid I will switch to it if
> it has an equivalent of csh's $array:q.

The following script is followed by its corresponding output (note the set
-A is redundant, and its not quite as convenient as in csh, where 'arr=
(one two three) sets $arr[1], $arr[2], and $arr[3] in one fell swoop):

set -x
arr="one two three"
echo $arr
echo ${arr[0]}
echo ${arr[1]}
arr[1]="four five six"
echo ${arr[1]}
echo ${arr[0]}
echo ${arr[*]}
echo ${#arr[*]}

+ arr=one two three
+ echo one two three
one two three
+ echo one two three
one two three
+ echo

+ arr[1]=four five six
+ echo four five six
four five six
+ echo one two three
one two three
+ echo one two three four five six
one two three four five six
+ echo 2
2
-- 
BURNS,JIM
Georgia Institute of Technology, Box 30178, Atlanta Georgia, 30332
uucp:	  ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt0178a
Internet: gt0178a@prism.gatech.edu