[comp.unix.wizards] csh programming problem

ellard@bbn.com (Dan Ellard) (03/13/90)

I am trying to write a shell script that takes several arguments and
passes them to child processes, i.e.

#!/bin/csh
foo $1 $2 ...
bar $1 $2 ...
exit 0

which I want to have the same effect as if I had typed to the shell:
foo $1 $2 ...
bar $1 $2 ...

Unfortunately, this method does not work when $1 is something like 'a b', since
$1 evaluates to the string ( a b ) without the quotes, so foo and bar
think that their first argument is 'a' and their second argument is 'b',
rather than that their first argument is 'a b'.

My solution to this problem is to build a new argument list, "requoting" each
argument, using this ugly piece of code:

#!/bin/csh
set count	= 1
set args	= $#argv
set new_args	= ""
while ($count <= $#argv)
	set  new_args = ( $new_args \'$argv[$count]\' )
	set count = `expr $count + 1`
end
foo $new_args
bar $new_args
exit 0

(I am open to suggestions concerning how to improve this)

This solves the original problem, but there are still more problems to
solve--  like handling quoted characters.  If I call this program with
$1 as \'foo, the backslash will be peeled off and my quoting scheme will
break.  Similar problems will arise if I try to use other characters that
have special meaning to the shell.  I could get around this by writing a
simple C program that re-inserts backslashes as necessary, but this seems
very clumsy.  Is there a good way to do this using either csh or sh, or
should I give up and write a C program to do it?

Thanks,
	Dan

---------------------------------------------------------------------------
Dan Ellard -- ellard@bbn.com
This line intentionally not left blank.

scott@cs.odu.edu (Scott Yelich) (03/15/90)

>I am trying to write a shell script that takes several arguments and
>passes them to child processes, i.e.
>#!/bin/csh
>foo $1 $2 ...
>bar $1 $2 ...
>exit 0
>which I want to have the same effect as if I had typed to the shell:
>foo $1 $2 ...
>bar $1 $2 ...
>  Unfortunately, this method does not work when $1 is something like
>'a b', since $1 evaluates to the string ( a b ) without the quotes, so
>foo and bar think that their first argument is 'a' and their second
>argument is 'b', rather than that their first argument is 'a b'.

foo "$@"
bar "$@"
--

 -----------------------------------------------------------------------------
 Scott D. Yelich                                 scott@cs.odu.edu [128.82.8.1]
 After he pushed me off the cliff, he asked me, as I fell, ``Why'd you jump?''
 -----------------------------------------------------------------------------

jik@athena.mit.edu (Jonathan I. Kamens) (03/15/90)

In article <SCOTT.90Mar14212616@oswy.cs.odu.edu>, scott@cs.odu.edu
(Scott Yelich) 
writes:
> >I am trying to write a shell script that takes several arguments and
> >passes them to child processes, i.e.
> >#!/bin/csh
> >...
> 
> foo "$@"
> bar "$@"

  Notice that he was talking about a *C shell* script.

  $@ is a *bourne shell* construct.  It doesn't work in the C shell.

Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8495			      Home: 617-782-0710

P.S. Any particular reason why your signature contained almost an entire
page full of blank lines?

jaap@sequent.UUCP (Jaap Vermeulen) (03/15/90)

ellard@bbn.com (Dan Ellard) writes:

>I am trying to write a shell script that takes several arguments and
>passes them to child processes, i.e.

>#!/bin/csh
>foo $1 $2 ...
>bar $1 $2 ...
>exit 0

>Unfortunately, this method does not work when $1 is something like 'a b', since
>$1 evaluates to the string ( a b ) without the quotes, so foo and bar

>(I am open to suggestions concerning how to improve this)

foo $1:q $2:q
bar $1:q $2:q

or:

foo $*:q

which is equivalent to

foo $@

in bourne shell

>This solves the original problem, but there are still more problems to
>solve--  like handling quoted characters.  If I call this program with
>$1 as \'foo, the backslash will be peeled off and my quoting scheme will
>break.  Similar problems will arise if I try to use other characters that
>have special meaning to the shell.

This should take care of all quoting etc.

jaap.
-- 
"Some call me Jaaper"				+---------------------------+
						| Sequent Computers Systems |
	Internet : sequent!jaap@uunet.uu.net	| Beaverton, Oregon	    |
	Uucp	 : ...uunet!sequent!jaap	+---------------------------+

iwarner@axion.bt.co.uk (Ivan Warner) (03/15/90)

In article <53408@bbn.COM>, ellard@bbn.com (Dan Ellard) writes:
> I am trying to write a shell script that takes several arguments and
> passes them to child processes, i.e.
> 
> #!/bin/csh
> foo $1 $2 ...
> bar $1 $2 ...
> exit 0
> 
> which I want to have the same effect as if I had typed to the shell:
> foo $1 $2 ...
> bar $1 $2 ...
> 
> Unfortunately, this method does not work when $1 is something like 'a
b', since
> $1 evaluates to the string ( a b ) without the quotes, so foo and bar
> think that their first argument is 'a' and their second argument is 'b',
> rather than that their first argument is 'a b'.
> 
> My solution to this problem is to build a new argument list, "requoting" each
> argument, using this ugly piece of code:
> 
> [UGLY code deleted]


	what on earth is wrong with:

#!/bin/csh 
foo "$1" "$2"
bar "$1" "$2"

	have I missed some subtle point, or is this not a `wizards' question

maart@cs.vu.nl (Maarten Litmaath) (03/16/90)

In article <1990Mar15.102758.17051@axion.bt.co.uk>,
	iwarner@axion.bt.co.uk (Ivan Warner) writes:
)In article <53408@bbn.COM>, ellard@bbn.com (Dan Ellard) writes:
)> I am trying to write a shell script that takes several arguments and
)> passes them to child processes, i.e.
)> 
)> #!/bin/csh
)> foo $1 $2 ...
)> bar $1 $2 ...
)...
)> Unfortunately, this method does not work when $1 is something like 'a
)b', [...]
)...
)	what on earth is wrong with:
)
)#!/bin/csh 
)foo "$1" "$2"
)bar "$1" "$2"
)
)	have I missed some subtle point, or is this not a `wizards' question

You missed a subtle point: what if the number of arguments is unknown in
advance?  You can't say "$@" in csh.
Still this isn't a wizards question, because the answer can be found in the
csh manual:

	% set argv=('a b' \\c \') 
	% set argv=($argv:q pp)
	% cat aap 
	for i
	do
		echo "=$i="
	done
	% sh aap $*:q
	=a b=
	=\c=
	='=
	=pp=
	% 
--
 1) Will 4.5BSD have wait5()?         |Maarten Litmaath @ VU Amsterdam:
 2) Sleep(3) should be sleep(2) again.|maart@cs.vu.nl, uunet!mcsun!botter!maart

scott@cs.odu.edu (Scott Yelich) (03/16/90)

>(Scott Yelich) 
>writes:
>>>I am trying to write a shell script that takes several arguments and
>>>passes them to child processes, i.e.
>>>#!/bin/csh
>>>...
>>foo "$@"
>>bar "$@"
>     Notice that he was talking about a *C shell* script.
>     $@ is a *bourne shell* construct.  It doesn't work in the C shell.

Well, if I was making a shell script that JUST passed already passed
values to sub shells.... I would write it in sh because there is a 
facility which makes this function extremely easy.  See his previous
message for the problems csh causes....

But, if he REALLY likes csh... perhaps?
 ------------------------------------------------------------------------------
eval f `repeat $#argv eval 'echo -n \"$1\"\  ; shift'`
 ------------------------------------------------------------------------------

However, I still prefer ``foo "$@"'' for its simplicity.

>   P.S. Any particular reason why your signature contained almost an entire
>   page full of blank lines?

Did it?  What about this one?  Are you sure?

--

 -----------------------------------------------------------------------------
 Scott D. Yelich                                 scott@cs.odu.edu [128.82.8.1]
 After he pushed me off the cliff, he asked me, as I fell, ``Why'd you jump?''
 -----------------------------------------------------------------------------

jik@athena.mit.edu (Jonathan I. Kamens) (03/16/90)

In article <SCOTT.90Mar15190447@osric.cs.odu.edu>, scott@cs.odu.edu (Scott 
Yelich) writes:
> Well, if I was making a shell script that JUST passed already passed
> values to sub shells.... I would write it in sh because there is a 
> facility which makes this function extremely easy.  See his previous
> message for the problems csh causes....

  As someone else has already pointed out, there is a functionality in
csh to make it extremely easy as well -- the ":q" qualifier to variable
expansion (That was a feature I didn't know about, too, so thanks to
whomever pointed it out!).

> >   P.S. Any particular reason why your signature contained almost an entire
> >   page full of blank lines?
> 
> Did it?  What about this one?  Are you sure?

  You're right, it was my newsreader (xrn is brain-damaged and stupid
about some things....).

Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8495			      Home: 617-782-0710

kon@mycroft.Stanford.EDU (Ronnie Kon) (03/16/90)

In article <53408@bbn.COM> ellard@BBN.COM (Dan Ellard) writes:
>I am trying to write a shell script that takes several arguments and
>passes them to child processes, i.e.
>
>#!/bin/csh
>foo $1 $2 ...
>bar $1 $2 ...
>exit 0
>
>which I want to have the same effect as if I had typed to the shell:
>foo $1 $2 ...
>bar $1 $2 ...
>

	First, apologies if this is a repeat of my earlier posting...we are
having some trouble with getting our postings out.

	It seems to me that the best way to deal with this is to put an
alias in your .cshrc, on the order of

		alias foobar	"foo \!* \; bar \!*"

This will do precisely what you want, and execute a whole lot faster.

	If you really need a shell script, you will need to echo the arguments
through sed to put backslashes before any double or back quotes appearing in
them, store the result into a variable, and then double quote the resulting
variable on the command lines.  This is really icky.

	In that this is pretty easilly discernable from the manual, I would
agree that it would be more at home in questions than in wizards.


-- 
-------------------------------------------------------------------------------
Ronnie Kon				|     "I don't know about your brain,
ronnie@mindcraft.com			|     but mine is really bossy"
...!{decwrl,hpda}!mindcrf!ronnie	|		-- Laurie Anderson
-------------------------------------------------------------------------------

maart@cs.vu.nl (Maarten Litmaath) (03/17/90)

In article <SCOTT.90Mar15190447@osric.cs.odu.edu>,
	scott@cs.odu.edu (Scott Yelich) writes:
)...
)eval f `repeat $#argv eval 'echo -n \"$1\"\  ; shift'`

It fails:

	% set argv=('a\
	b c')
	% cat chkargs
	#!/bin/sh

	for i
	do
		echo "<$i>"
	done
	% eval chkargs `repeat $#argv eval 'echo -n \"$1\"\  ; shift'`
	<a b c>
	% 

What the hell is wrong with using the `:q' modifier anyway?

)However, I still prefer ``foo "$@"'' for its simplicity.

I prefer sh for other reasons.
--
 1) Will 4.5BSD have wait5()?         |Maarten Litmaath @ VU Amsterdam:
 2) Sleep(3) should be sleep(2) again.|maart@cs.vu.nl, uunet!mcsun!botter!maart