A method describing how is discussed in ORA's "Unix Power Tools." (Hint:
embed the if...then in an "eval" statement.)
[From "ftp://ftp.ora.com/pub/examples/power_tools/unix/split/csh_init"]
# An example of putting if-then-else in an alias.
# # (This alias compiles a C program and makes the executable unreadable.)
# alias C 'eval "if (\!* =~ *.c) then \\
# echo "C quitting: no .c on end of \!* please." \\
# else \\
# if (-e \!*) mv \!* \!*.old \\
# echo \!*.c SENT TO cc \\
# cc -s \!*.c -o \!* \\
# if (-e \!*) chmod 311 \!* \\
# endif"'
> i have looked in the faq of this newsgroups but found no hint how to
> accomplish this. point 5.7 refers to additional information which
> can be found at
> ftp.uwp.edu (204.95.162.190):pub/vi/docs/shell-100.BetaA.Z
> utsun.s.u-tokyo.ac.jp:misc/vi-archive/docs/shell-100.BetaA.Z
> but the first link exists no more (no dns entry) and for the second link
> i only get timeouts. does somebody of you have this additional doc?
I remember this file: incorrect, incomplete, ill-advised.
A more general method is to set up aliases to "source" scripts
having the "function body." The usual csh history tomfoolery may be
manipulated to pass command line parameters. Many years ago I went
around and around via email perfecting for another query a robust
method of simulating command line parameters in "source"d files in
t/csh, but it is lost and I cannot recall the details; presumably
you will follow the same mental processes that I did to eventually
to come to the same successful conclusion.
Okay, now the obligatory link:
http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/
http://riceinfo.rice.edu/Computer/Documents/Unix/unix18.pdf
... and, if you are still interested in t/csh scripting, a document which
may be of technical value to you is:
ftp://gatekeeper.dec.com/pub/misc/csh-tricks/
-Brian
Net-Tamer V 1.08X - Test Drive
Yes.
--
Barry Margolin, bar...@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
> i am wondering that it is possible to use nested double quotes. the outer
> double quotes are the bound for the eval expression and inside this
> expression the echo uses double quotes likewise.
Now that mention it is is either a typographic error or a scripting error
on the part of the ORA authors. T/csh cannot have embedded dquotes (all
such "bournisms" are not so logically implemented...)
> this example works fine and you can't imagine how happy i am now. :-)))
> many thanks.
Glad it worked out for you; as for myself I would be as pleased to be
able to speak German as well as you speak English. Three years of German
in high school and I am still reticent to practise it.
-Brian
>i tried the following:
>alias foo 'eval "echo "hello world""'
This does the trick:
set verbose echo
alias foo 'eval "echo ''"'"'"'"'"'"'"''hello world''"'"'"'"'"'"'"''"'
foo
unset verbose echo
--
Klaus "\"r" Frank
>>>> i am wondering that it is possible to use nested double quotes.
Here's the second example that was missing from in my reply:
alias foo 'eval "if ($a == $a) then \\
echo ''"'"'"'"'"'"'"''*bar''"'"'"'"'"'"'"'' \\
endif"'
or shorter
alias foo 'eval "if ($a == $a) then \\
echo "'"'"'"'"'"'"*bar"'"'"'"'"'"'" \\
endif"'
The general pattern is to undo the quoting, insert "'"'"'"'" for a double
quote, and continue the quoting again. If there were another level of
eval, you would need a 27-character construct for the innermost double quote.
It should be possible to support the transformation from simple commands to
nested commands with appropriate sed commands and to apply them repeatedly.
Any volunteers?
>Klaus Frank <kla...@informatik.rwth-aachen.de> wrote:
>> begin quotation
alias foo 'eval "if ($a == $a) then \\
echo ''"'"'"'"'"'"'"''*bar''"'"'"'"'"'"'"'' \\
endif"'
>> end quotation
>by the way, the example isn't working. when i use the alias i always get
>a ' Unmatched ". '.
I checked it again in csh and tcsh; it works. Try to copy/paste with the mouse.
>your example looks impressive but i don't understand it. what is going on
>with those many single- and double quotes?
Again, the best way to see the quotes at the different stages of interpretation
is to use the `echo' and `verbose' variables of the csh when defining the alias
and when using the alias.
>can you explain it a little bit more?
We want to end up with
echo "*bar"
. So the first round of eval should get the one argument
"echo "'"'"*bar"'"'""
because this will yield the concatenation of \e\c\h\o\ , \", \*\b\a\r, and \".
Hence, the eval command that the alias foo should contain should be
eval "echo "'"'"*bar"'"'""
. Note that I have substituted \'\"\' for any \". (I'm leaving out the if line,
the endif line and the escaped newlines here.) Now, the alias command will use
single quotes to quote the eval command. Because the eval command does contain
four single quotes, they must be quoted using outside the single quoted content
using paired double quotes. That is, a string
xxx'yyy'zzz
would be quoted as
alias that 'xxx'"'"'yyy'"'"'zzz'
. Note that I have substituted \"\'\" for any \'. Hence, our eval command will
fit into the alias command as
alias foo 'eval "echo "'"'"'"'"'"'"*bar"'"'"'"'"'"'""'
because this will yield the concatenation of \e\v\a\l\ \"\e\c\h\o\ \", \',
\", \', \"\*\b\a\r\", \', \", \', and \"\".
(The first version of my alias which you quoted was inconsistent as I didn't
include the second double quote in the single quote quotation.)
The obvious summary is: don't do that manually, it's error-prone. But it
should be possible to automate the process sketched above by sed scripts
or, say, $YOUR_FAVORITE_EDITOR's macros. It might be possible to write a
shell script that reads a script and outputs a transformed script that
uses the input inside eval or alias commands, depending on command-line
parameters to the transformator script. Maybe it's even possible to use
an alias instead of a script, so one could write
make_alias foo <<EOF
echo -n starting command.....
if ( { command } ) then
echo ok
else
echo fail
endif
EOF
to make the appropriate alias out of the here-doc-quoted lines with
correct quoting of quotes and newlines. This would involve advanced
use of csh eval and possibly csh workarounds. Again, any volunteers?
--
#!/bin/sh
set eval '"$@"'; "$@"
echo Done.
>Maybe it's even possible to use
>an alias [...], so one could write
>make_alias foo <<EOF
>echo -n starting command.....
>if ( { command } ) then
> echo ok
>else
> echo fail
>endif
>EOF
>to make the appropriate alias out of the here-doc-quoted lines with
>correct quoting of quotes and newlines. [...]
I played around with csh and ended up with a little shar file
which contains a similar alias. I don't know its limitations yet.
(Yes, writing and sourcing a file in /tmp is a security hole.)
The new csh `keywords' :-) are make_alias and "end_alias" (with dquotes!).
Volunteers are invited to define try/"catch"/"endtry" blocks with possible
throw statements... :-)
#!/bin/sh
# This is a shell archive (produced by GNU shar 4.0).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 2000-11-26 18:30 MET by <klausf@pfitzner>.
# Source directory was `/home/private/students/klausf'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 256 -rwxr-xr-x make_alias.sed
# 270 -rw-r--r-- make_alias.csh
# 253 -rwxr-xr-x example.csh
#
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
shar_touch=touch
else
shar_touch=:
echo 'WARNING: not restoring timestamps'
fi
rm -f 1231235999 $$.touch
#
# ============= make_alias.sed ==============
if test -f 'make_alias.sed' && test X"$1" != X"-c"; then
echo 'x - skipping make_alias.sed (File already exists)'
else
echo 'x - extracting make_alias.sed (text)'
sed 's/^X//' << 'SHAR_EOF' > 'make_alias.sed' &&
#!/bin/sed -f
#
# Make the innermost eval command
s/'/'"'"'/g;
1s/^/eval '/;
$s/$/'/;
#
# Escape excamation marks and newlines
s/!/\\!/g;
s/$/\\\\/g
#
# Finish the alias command
s/'/'"'"'/g;
1s/^/alias @alias_name@ '/;
$a\
;echo arguments>/dev/null'
# eof
SHAR_EOF
$shar_touch -am 11261755100 'make_alias.sed' &&
chmod 0755 'make_alias.sed' ||
echo 'restore of make_alias.sed failed'
shar_count="`wc -c < 'make_alias.sed'`"
test 256 -eq "$shar_count" ||
echo "make_alias.sed: original size 256, current size $shar_count"
fi
# ============= make_alias.csh ==============
if test -f 'make_alias.csh' && test X"$1" != X"-c"; then
echo 'x - skipping make_alias.csh (File already exists)'
else
echo 'x - extracting make_alias.csh (text)'
sed 's/^X//' << 'SHAR_EOF' > 'make_alias.csh' &&
#!/bin/echo -source-this-file->
X
alias make_alias 'echo Defining alias, finish with '"'"'"end_alias"'"'"';\\
X <<"end_alias" ./make_alias.sed | \\
X sed -e s/@alias_name@/\!\!:1/ >/tmp/make_alias$$; \\
X source /tmp/make_alias$$; \\
X rm /tmp/make_alias$$; \\
'
SHAR_EOF
$shar_touch -am 11261756100 'make_alias.csh' &&
chmod 0644 'make_alias.csh' ||
echo 'restore of make_alias.csh failed'
shar_count="`wc -c < 'make_alias.csh'`"
test 270 -eq "$shar_count" ||
echo "make_alias.csh: original size 270, current size $shar_count"
fi
# ============= example.csh ==============
if test -f 'example.csh' && test X"$1" != X"-c"; then
echo 'x - skipping example.csh (File already exists)'
else
echo 'x - extracting example.csh (text)'
sed 's/^X//' << 'SHAR_EOF' > 'example.csh' &&
#! /usr/local/bin/tcsh -f
X
source ./make_alias.csh
X
X
make_alias example >&/dev/null
X echo 'First argument is "!!:1".'
X if ($USER == klausf) then
X echo Hi, Klaus...
X else
X echo Hi...
X endif
X echo 'Done.'
"end_alias"
X
example some_argument
SHAR_EOF
$shar_touch -am 11261758100 'example.csh' &&
chmod 0755 'example.csh' ||
echo 'restore of example.csh failed'
shar_count="`wc -c < 'example.csh'`"
test 253 -eq "$shar_count" ||
echo "example.csh: original size 253, current size $shar_count"
fi
exit 0
>i am writing code in tcsh and i would like to have some kind of functions.
>[...] actually i have the following small piece of code which is heavily
>used in my program:
>echo -n starting command.....
>if ( { command } ) then
> echo ok
>else
> echo fail
>endif
>i would like to use a function/alias for this program. [...]
>it is possible to write an alias for the echo command but i am
>not able to write an alias for the if/then/else command. [...]
Using an appropriate meta-alias defined below, you can actually write:
make_alias check_command
echo -n 'starting command "!!:1" .....'
if ( { !!:1 } ) then
echo ok
else
echo fail
endif
"end_alias"
check_command true
check_command false
Here's the meta-alias in its self-contained version. If you want to hack
on it, ask me for the unquoted unquoted sed scriptfile and the pure alias.
alias make_alias '\\
<<"end_alias" sed -e '"'"'\\
#\\!/bin/sed -f\\
#\\
## Make the eval command\\
# quote quotes\\
s/'"'"'"'"'"'"'"'"'/'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'/g;\\
# enclose with quotes\\
1s/^/eval '"'"'"'"'"'"'"'"'/;\\
$s/$/'"'"'"'"'"'"'"'"'/;\\
#\\
## Make the alias command\\
# escape exclamation marks and newlines\\
s/\\!/\\\\!/g;\\
s/$/\\\\/g\\
# quote quotes\\
s/'"'"'"'"'"'"'"'"'/'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'/g;\\
# enclose with quotes\\
1s/^/alias @alias_name@ '"'"'"'"'"'"'"'"'/;\\
$a\\\
;echo >/dev/null'"'"'"'"'"'"'"'"'\\
#^^^^^^^^^^^^^^^ (workaround against printing of arguments)\\
'"'"' | \\
sed -e s/@alias_name@/\!\!:1/ >/tmp/make_alias$$; \\
source /tmp/make_alias$$; \\
rm /tmp/make_alias$$; \\
'
--
Klaus M. Frank kla...@Pool.Informatik.RWTH-Aachen.DE
"brian hiles" <b...@rainey.blueneptune.com> wrote in message
news:t1j4c1p...@corp.supernews.com...
> Volker Schuetz <volker...@nokia.com> wrote:
> > i am writing code in tcsh and i would like to have some kind
> > of functions. unfortunately the tcsh doesn't support functions
> > but only aliases. maybe it is possible to use a complex
> > alias as an function replacement?
> > actually i have the following small piece of code which is
> > heavily used in my program:
> > echo -n starting command.....
> > if ( { command } ) then
> > echo ok
> > else
> > echo fail
> > endif
> > i would like to use a function/alias for this program. this
> > would make my code much more readable. i would look like:
> > check_command command1
> > check_command command2
> > check_command command2
> > it is possible to write an alias for the echo command but i am
> > not able to write an alias for the if/then/else command. i can
> > use !* to use an argument inside an alias definition so it is
> > no problem to transfer the argument. but if i understand the
> > documentation of the tcsh correctly it is not allowed to write the
> > if/then/else command in one line. but i can't set an alias to
> > a command covering more than one line.
>
> A method describing how is discussed in ORA's "Unix Power Tools." (Hint:
> embed the if...then in an "eval" statement.)
>
> [From "ftp://ftp.ora.com/pub/examples/power_tools/unix/split/csh_init"]
>
> # An example of putting if-then-else in an alias.
> # # (This alias compiles a C program and makes the executable unreadable.)
> # alias C 'eval "if (\!* =~ *.c) then \\
> # echo "C quitting: no .c on end of \!* please." \\
> # else \\
> # if (-e \!*) mv \!* \!*.old \\
> # echo \!*.c SENT TO cc \\
> # cc -s \!*.c -o \!* \\
> # if (-e \!*) chmod 311 \!* \\