Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: whence question



Ray Andrews wrote on Sat, Jan 14, 2017 at 11:51:08 -0800:
> On 14/01/17 10:55 AM, Bart Schaefer wrote:
> >
> >   local _args=( ${~@} )
> >
> >
> [...] I almost read that one.

What you wrote is:

|local _args=`eval echo $@`||
||_args=( ${(z)_args} )|

Your input here was the positional arguments ($@), which are a list of
words parsed from the command line.

The input to eval is an unparsed command line string.  Therefore,
passing $@ to eval is a type mismatch.  It will cause filenames with
spaces to be split.  The way to interpolate variables into eval's
arguments is with (q), e.g., the following are equivalent:
.
     echo $foo
     eval echo ${(q)foo}

Next, using 'echo' will not safely round-trip arbitrary values;
filenames with spaces or backslashes would be mangled by it (even
without 'eval').

There are other problems here (splitting on spaces is the least of your
concerns with that 'eval'; it inteprets data as code), but circling back
to Bart's solution, what it does right is that it uses the correct data
types and applies the correct transformation.  That's because «${~@}»
happens to be a transformation that takes a "$@", interprets every word
in it as a glob, and returns a list of words.  (Without the round
parentheses, it'd return something else.)  It's documented in "Parameter
expansion" in zshexpn(1); grep for GLOB_SUBST.

Note also that the round parentheses are required, to declare an array
rather than a single string.

Cheers,

Daniel



Messages sorted by: Reverse Date, Date, Thread, Author