[comp.unix.shell] Delayed evaluation of csh variables?

chris@asylum.gsfc.nasa.gov (Chris Shenton) (12/11/90)

I'm trying to do a script where I set up a variable to contain a template,
then later instantiate one of the variables; the whole thing then is passed
to a command. Something like this, conceptually:

#!/bin/csh
set COMMAND = "command"
set OPTION_TEMPLATE = "-Z '$File'"	# Want *literal* $File
					#   -- to be evaluated *later* --
					#   but csh evaluates it now and dies
foreach File ( $* )			# Instantiate in $OPTION_TEMPLATE ??
	$COMMAND $OPTION_TEMPLATE	# doesn't work
end


Is there a way to do this? 

Thanks in advance.
--
chris@asylum.gsfc.nasa.gov, ...!uunet!asylum.gsfc.nasa.gov!chris, PITCH::CHRIS

tchrist@convex.COM (Tom Christiansen) (12/11/90)

In article <CHRIS.90Dec10160308@asylum.gsfc.nasa.gov> chris@asylum.gsfc.nasa.gov (Chris Shenton) writes:
:I'm trying to do a script where I set up a variable to contain a template,
:then later instantiate one of the variables; the whole thing then is passed
:to a command. Something like this, conceptually:
:
:#!/bin/csh

You forgot the -f there.  That'll slow you down a lot and 
could have unforeseen side-effects.

:set COMMAND = "command"
:set OPTION_TEMPLATE = "-Z '$File'"	# Want *literal* $File
:					#   -- to be evaluated *later* --
:					#   but csh evaluates it now and dies
:foreach File ( $* )			# Instantiate in $OPTION_TEMPLATE ??
:	$COMMAND $OPTION_TEMPLATE	# doesn't work
:end

:Is there a way to do this? 

Sure, you could use an eval (we seem to get kind of question one a lot).
One of your problems is using the csh at all.  It's a real pain.  I've
heard Bill Joy will tell you he didn't understand expression evaluation
when he wrong it.  It does show.  You could do this:

    set OPTION_TEMPLATE = '-Z $File'	# Want *literal* $File

and then this:
    eval $COMMAND $OPTION_TEMPLATE	

but please trust me when I tell you that you do not want to be 
writing scripts in csh.  Honest.

--tom
--
Tom Christiansen		tchrist@convex.com	convex!tchrist
"With a kernel dive, all things are possible, but it sure makes it hard
 to look at yourself in the mirror the next morning."  -me

chris@asylum.gsfc.nasa.gov (Chris Shenton) (12/12/90)

Thanks to everyone who responded (mail and posts) on my query. This is a
``best-of'' from the suggestions.

1. The quoting can be simplified by nixing the " and using ' instead.
2. Eval -- this is the key -- is needed to instantiate the variable in the
   string. 


Here's the simplest example thing I've come up with:

	#!/bin/csh -vxf			# show whazzup; ignore .cshrc
	set COMMAND = 'ls -l $File'	# simple single quotes do the trick
	foreach File ( $* )		# do all command line arguments
		eval $COMMAND		# eval to instantiate $File
	end

tchrist@convex.com insists that I shouldn't be doing any programming in
csh. Probably true, but I'm too lazy to get intimate with sh for such short
stuff. (I'd rather learn bash!) 


Again, many thanks to everyone.

Ciao!

--
chris@asylum.gsfc.nasa.gov, ...!uunet!asylum.gsfc.nasa.gov!chris, PITCH::CHRIS

Harald.Eikrem@elab-runit.sintef.no (12/13/90)

I believe there are cases when csh outperforms Bourne shell, e.g. when you
are on a slow system and need access to expression evaluation, exemplified by:

=========
#!/bin/csh -f
# pickcolor - pick an X application background color semirandomly
if ( $#argv == 0 ) then
        set argv=( BlanchedAlmond Bisque NavajoWhite YellowGreen \
                   BlanchedAlmond Honeydew2 Tan LightSalmon LavenderBlush \
                   MistyRose Moccasin LightSteelBlue NavajoWhite PaleTurquoise \
                   BlanchedAlmond Khaki PaleGoldenrod Lavender Tan Salmon \
                   Orchid Seashell3 PaleVioletRed Thistle NavajoWhite Wheat )
endif
set pick=1
if ( $#argv > 1 ) then
        /usr/games/random -e $#argv
        @ pick = $status + 1
endif
echo $argv[$pick]
=========


For a different case, save the following as ~/csh/path and then
    alias path source ~/csh/path "'\!*'"
then you have a simple csh $path manipulator.
I like to see this done for ksh/bash......			--Harald E

=========
# csh search path management procedure
# - invoke through alias path source <thisdirectory>path "'\!*'"
#
if ( ! $?path ) set path = ""
if ( "$path" == '' && '!*' !~ [./~]* && '!*' !~ \$?* ) then
		set path = (. ~/bin /usr/local/bin /usr/ucb /bin /usr/bin)
		echo 'No path set; using default settings.\
'$path
else if ( '!*' == '' ) then
	echo $path
else if ( '!*' == '-' || '!*' == '-$' ) then
	if ( $#path == 1 ) then
		echo 'Only one path element left, will not unset $path'
	else
		@ n__ = $#path - 1
		set path = ($path[-$n__])
		echo $path
	endif
	unset n__
else if ( '!*' == '-^' ) then
	if ( $#path == 1 ) then
		echo 'Only one path element left, will not unset $path'
	else
		set path = ($path[2*])
		echo $path
	endif
	unset n__
else if ( '!*' =~ \-[1-9] || '!*' =~ \-[1-9][0-9] ) then
	@ arg__ = - !^
	if ( $arg__ > $#path ) then
		if ( $#path == 1 ) then
			echo 'There is currently only '$#path' element in $path'
		else
			echo 'There are currently '$#path' elements in $path'
		endif
	else if ( $#path == 1 ) then
		echo 'Only one path element left, will not unset $path'
	else if ( $arg__ == $#path ) then
		@ n__ = $arg__ - 1
		set path = ($path[-$n__])
		echo $path
	else
		@ n__ = $arg__ - 1
		@ r__ = $arg__ + 1
		set path = ($path[-$n__] $path[$r__-])
		echo $path
	endif
	unset arg__ n__ r__
else if ( '!*' =~ [1-9^]\ [./~]* || '!*' =~ [1-9][0-9]\ [./~]* || \
	  '!*' =~ [1-9^]\ \$[_a-zA-Z0-9]* || \
	  '!*' =~ [1-9][0-9]\ \$[_a-zA-Z0-9]* ) then
	if ( !^ > $#path + 1 ) then
		if ( $#path == 1 ) then
			echo 'There is currently only '$#path' element in $path'
		else
			echo 'There are currently '$#path' elements in $path'
		endif
	else if ( !^ <= 1 || !^ == ^ ) then
		set path = (!:2* $path)
		echo $path
	else if ( !^ > $#path ) then
		set path = ($path !:2*)
		echo $path
	else
		@ r__ = !^ - 1
		set path = ($path[-$r__] !:2* $path[!{^}*])
		echo $path
	endif
	unset arg__ n__ r__
else if ( '!*' =~ [./~]* || '!*' =~ \$[_a-zA-Z0-9]* ) then
	set path = ($path !*)
	echo $path
else echo 'Usage: path { -^ | -$ | - | -<n> | <n> pathname(s) | pathname(s) }\
meaning:\
	-^		strip first element from $path.\
	-$ or -		strip last element.\
	-<n>		strip element number <n>, numbering from 1 up.\
	<n> pathname(s)	insert pathname(s) before element <n>, where\
			<n> can be ^ if before first element.\
	pathname(s)	add pathname(s) beyond last element.\
\
A valid pathname should start with [./~], or be a shell variable constituting\
one or more valid pathnames.'
endif