In zsh, parameters are set like this:
% foo=bar % echo $foo bar
Spaces before or after the = are frowned upon:
% foo = bar zsh: command not found: foo
Also, set
doesn't work for setting parameters:
% set foo=bar % set foo = bar % echo $foo %
Note that no error message was printed. This is because both of these
commands were perfectly valid; the set
builtin assigns its
arguments to the positional parameters ($1
, $2
,
etc.).
% set foo=bar % echo $1 foo=bar % set foo = bar % echo $3 $2 bar =
If you're really intent on using the csh syntax, define a function like this:
% set () { > eval "$1$2$3" > } % set foo = bar % set fuu=brrr % echo $foo $fuu bar brrr
But then, of course you can't use the form of set
with options,
like set -F
(which turns off filename generation). Also, the
set
command by itself won't list all the parameters like it
should. To get around that you need a case
statement:
% set () { > case $1 in > -*|+*|") builtin set $* ;; > *) eval "$1$2$3" ;; > esac > }
For the most part, this should make csh users happy.
The following sh-style operators are supported in zsh:
% unset null % echo ${foo-xxx} bar % echo ${null-xxx} xxx % unset null % echo ${null=xxx} xxx % echo $null xxx % echo ${foo=xxx} bar % echo $foo bar % unset null % echo ${null+set} % echo ${foo+set} set
Also, csh-style : modifiers may be appended to a parameter substitution.
% echo $PWD /home/learning/pf/zsh/zsh2.00/src % echo $PWD:h /home/learning/pf/zsh/zsh2.00 % echo $PWD:h:h /home/learning/pf/zsh % echo $PWD:t src % name=foo.c % echo $name foo.c % echo $name:r foo % echo $name:e c
The equivalent constructs in ksh (which are also supported in zsh) are a
bit more general and easier to remember. When the shell expands
${foo#pat}
, it checks to see if pat matches a
substring at the beginning of the value of foo
. If so, it
removes that portion of foo
, using the shortest possible match.
With ${foo##pat}
, the longest possible match is removed.
${foo%pat}
and ${foo%%pat}
remove the
match from the end. Here are the ksh equivalents of the :
modifiers:
% echo ${PWD%/*} /home/learning/pf/zsh/zsh2.00 % echo ${PWD%/*/*} /home/learning/pf/zsh % echo ${PWD##*/} src % echo ${name%.*} foo % echo ${name#*.} c
zsh also has upper/lowercase modifiers:
% xx=Test % echo $xx:u TEST % echo $xx:l test
% echo $name:s/foo/bar/ bar.c % ls foo.c foo.h foo.o foo.pro % for i in foo.*; mv $i $i:s/foo/bar/ % ls bar.c bar.h bar.o bar.pro
One possible source of confusion is the fact that in zsh, the result of parameter substitution is not split into words. Thus, this will not work:
% srcs='glob.c exec.c init.c' % ls $srcs glob.c exec.c init.c not found
This is considered a feature, not a bug. If splitting were done by default, as it is in most other shells, functions like this would not work properly:
$ ll () { ls -F $* } $ ll 'fuu bar' fuu not found bar not found % ll 'fuu bar' fuu bar not found
Of course, a hackish workaround is available in sh (and zsh):
% setopt shwordsplit % ll () { ls -F "$@" } % ll 'fuu bar' fuu bar not found
If you like the sh behaviour, zsh can accomodate you:
% ls ${=srcs} exec.c glob.c init.c % setopt shwordsplit % ls $srcs exec.c glob.c init.c
Another way to get the $srcs
trick to work is to use an array:
% unset srcs % srcs=( glob.c exec.c init.c ) % ls $srcs exec.c glob.c init.c
or an alias:
% alias -g SRCS='exec.c glob.c init.c' % ls SRCS exec.c glob.c init.c
Another option that modifies parameter expansion is RCEXPANDPARAM
:
% echo foo/$srcs foo/glob.c exec.c init.c % setopt rcexpandparam % echo foo/$srcs foo/glob.c foo/exec.c foo/init.c % echo foo/${^srcs} foo/glob.c foo/exec.c foo/init.c % echo foo/$^srcs foo/glob.c foo/exec.c foo/init.c