Hey! The (z) expansion flag is documented to return an array, but this is not the case if we have only one word: 16:24 ❱ print -l ${${(z)${:-word1}}[1]} w 16:24 ❱ print -l ${${(z)${:-word1 word2}}[1]} word1 This can be worked around with A: 16:29 ❱ print -l ${${(Az)${:-word1}}[1]} word1 16:29 ❱ print -l ${${(Az)${:-word1 word2}}[1]} word1 But older versions of Zsh does not have that. Is there another way? Is there an easy way to know if something is an array or a string? I am using subscripting for that but maybe there are better ways. -- Don't over-comment. - The Elements of Programming Style (Kernighan & Plauger)
On Mon, Nov 29, 2021 at 4:32 PM Vincent Bernat <bernat@luffy.cx> wrote:
>
> Is there an easy way to know if something is an array or a string?
> I am using subscripting for that but maybe there are better ways.
If you had a parameter, you could use ${(t)foo} or $parameters[foo] to
find its type. However, if you had a parameter you wouldn't have this
problem to begin with.
foo=(${(z)...})
Here foo is always an array.
Roman.
On Mon, Nov 29, 2021, at 10:31 AM, Vincent Bernat wrote:
> The (z) expansion flag is documented to return an array
Is it? The 5.8 man page does not mention "array" even once.
z Split the result of the expansion into words using shell
parsing to find the words, i.e. taking into account any
quoting in the value. Comments are not treated specially but
as ordinary strings, similar to interactive shells with the
INTERACTIVE_COMMENTS option unset (however, see the Z flag
below for related options)
Note that this is done very late, even later than the `(s)'
flag. So to access single words in the result use nested
expansions as in `${${(z)foo}[2]}'. Likewise, to remove the
quotes in the resulting words use `${(Q)${(z)foo}}'.
--
vq
> On 29 November 2021 at 16:50 Lawrence Velázquez <larryv@zsh.org> wrote:
> On Mon, Nov 29, 2021, at 10:31 AM, Vincent Bernat wrote:
> > The (z) expansion flag is documented to return an array
>
> Is it? The 5.8 man page does not mention "array" even once.
Indeed, there's not really any notion of "returning an array". There's
just the question of how something is treated at a particular part
of parameter expansion. Forcing something to be treated in a
particular way by tweaking the expansion is possible, forcing
a particular value always to be treated in some way regardless
of context isn't, to the best of my knowledge. The context always
has the last say --- consider quoting, and the flags to circumvent
quoting, for example. They're all (over the top metaphor coming)
breadcrumbs to lead us of the labyrinth that's ended up at a
corner.
More generally, return values and explicit expression typing are things
shells, including zsh, are very bad at; it's particularly annoying with
zsh, however, owing to the complexities you can get into, and
nested parameters are one of the worst examples.
Feel free to find a counterexample, obviously.
pws
❦ 29 November 2021 11:50 -05, Lawrence Velázquez:
>> The (z) expansion flag is documented to return an array
>
> Is it? The 5.8 man page does not mention "array" even once.
>
> z Split the result of the expansion into words using shell
> parsing to find the words, i.e. taking into account any
> quoting in the value. Comments are not treated specially but
> as ordinary strings, similar to interactive shells with the
> INTERACTIVE_COMMENTS option unset (however, see the Z flag
> below for related options)
>
> Note that this is done very late, even later than the `(s)'
> flag. So to access single words in the result use nested
> expansions as in `${${(z)foo}[2]}'. Likewise, to remove the
> quotes in the resulting words use `${(Q)${(z)foo}}'.
When I read "split", I read "into an array". I must miss something.
Also, it works when there is something to split, but not when there is
only one word.
--
Don't use conditional branches as a substitute for a logical expression.
- The Elements of Programming Style (Kernighan & Plauger)
❦ 29 November 2021 17:34 +01, Roman Perepelitsa: >> Is there an easy way to know if something is an array or a string? >> I am using subscripting for that but maybe there are better ways. > > If you had a parameter, you could use ${(t)foo} or $parameters[foo] to > find its type. However, if you had a parameter you wouldn't have this > problem to begin with. Thanks for the tips! > foo=(${(z)...}) > > Here foo is always an array. Yes, that's what I have done. -- Let the machine do the dirty work. - The Elements of Programming Style (Kernighan & Plauger)
On Mon, Nov 29, 2021 at 8:51 AM Lawrence Velázquez <larryv@zsh.org> wrote: > > On Mon, Nov 29, 2021, at 10:31 AM, Vincent Bernat wrote: > > The (z) expansion flag is documented to return an array > > Is it? The 5.8 man page does not mention "array" even once. True, but "split" usually implies $@ -variety results. Also: > [...]. So to access single words in the result use nested > expansions as in `${${(z)foo}[2]}'. That would lead one to believe that ${${(z)foo}[1]} also returns a single word, but as PWS notes the context may alter that.
On Mon, Nov 29, 2021 at 7:31 AM Vincent Bernat <bernat@luffy.cx> wrote:
>
> 16:29 ❱ print -l ${${(Az)${:-word1}}[1]}
> word1
>
> But older versions of Zsh does not have that. Is there another way?
The only way I can come up with is to append a dummy extra element; instead of
${${(z)something}[1]}
use
${${(z)${:-$something \\}}[1]}