Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Final touch? RE: PATCH: more substitution documentation
- X-seq: zsh-workers 5855
- From: "Andrej Borsenkow" <borsenkow.msk@xxxxxx>
- To: "Peter Stephenson" <pws@xxxxxxxxxxxxxxxxx>, "Zsh hackers list" <zsh-workers@xxxxxxxxxxxxxx>
- Subject: Final touch? RE: PATCH: more substitution documentation
- Date: Thu, 18 Mar 1999 18:23:37 +0300
- Importance: Normal
- In-reply-to: <9903180916.AA38484@xxxxxxxxxxxxxxxxx>
- Mailing-list: contact zsh-workers-help@xxxxxxxxxxxxxx; run by ezmlm
I think, there is a couple more things that need to be explicitly stated.
1. Nested substitution:
1.1 substitution is done reqursively, including implicit word splitting if
SH_WORD_SPLIT is set. This may be obvious, but it is not so in manual. (I
believed for a long time, that field splitting is done once after all is
done)
1.2 The result of substitution is a *list* (possibly empty or with having
only one element).
1.3 Implicit joinig in quotes happens by *outer* subst when it is going to
use the value; not by *inner* subst after the value is computed. Again, I
always believed, (@) prevents *outer* level from joining words (hence all
this confusion). That explains (for me):
itsrm2% foo=(a b c d)
itsrm2% args "${(@)foo[2,3]}"
2
b
c
First the foo[2,3] is taken. Because of (@) it is not joined. This is still
vague, as we actually have two lists here - $foo and $foo[2,3]. It seems,
that foo[2,3] is treated as a single entity. It probably needs to be
explained too. That is, the difference betwee foo[...] and ${...}[...].
itsrm2% args "${${(@)foo}[2,3]}"
1
b
Outer substitution first joins the list.
itsrm2% args "${(@)${foo}[2,3]}"
0
Inner subst does join the list foo (as it is in quotes) - outer one does
*not* join it - and we get a list with one word. Rules 1.2 and 1.3.
2. (@) flag
In double quotes, it prevents the words of list that results from inner
subst to be joined and converted to scalar, even if list has only single
word (this is very important)!! That is, even if inner subst results in one
word, it still treated as list (array) with one word.
3. Splitting
To my great suprise I found, that splitting works even in double quotes!!!
itsrm2% args "${(f)$(print "a\nb\nc")}"
3
a
b
c
itsrm2% foo=axbxc
itsrm2% args "${(s/x/)foo}"
3
a
b
c
foo="a b c"
itsrm2% args "$=foo"
3
a
b
c
That is, no (@) is needed in first case (that is also logical, if we take
the meaning of (@) as in 2). Again, it should be mentioned explicitly. This
is also logical, if we assume, that joinig occurs in outer subst - as here
we have no outer subst at all :-)
4. $= meaning
As you see, the spplitting, that is done by $= is *not* the same as default
field splitting with SH_WORD_SPLIT. The latter does not happen in double
quotes - the former does. I also think it is O.K. - but then, the wording in
manual must be changed. Not "turns on SH_WORD_SPLIT" - but "performs word
splitting using the same rules as SH_WORD_SPLIT".
Looking back, this makes the whole story probably predictable :-) this also
explains difference between "${foo[1]}" and "${${(@)foo}[1]}". foo[1] is
treated as single entity and results in first elemnt of foo. In the latter
case, first value of foo is taken (list), that is then passed as list ((@)
flag) to upper subst; that joins the list together (no (@)) and treats it as
scalar. Nice. To make the outer treat list as list (array) you need te
second (@) - exactly as Sven said.
So, the whole for a ${(flags)var-mods} looks like
1. take the value of var. The result is list (array) of words (may be empty
or having only one element)
2. If this is quoted and no (@) is present, join the list with the first
character if IFS (I think, it is correct? Not always with space?) thus
producing a single word (again, actually a list with single word)
3. apply mods separately for every word in list
4. join the words again if (j) is present
5. split using (s) or $= if present
6. If no $= or (s) is present and the whole is not quoted, apply
SH_WORD_SPLIT:
itsrm2% foo="x y:a b"
itsrm2% setopt shwordsplit
itsrm2% args ${(s/:/)foo}
2
x y
a b
itsrm2% args ${foo}
3
x
y:a
b
7. the result is again a (possibly empty) list of words. If the whole is
not quoted, the empty words are removed
The steps 1-7 are done recursively for every nested substitution (I hate
this word - spelling, that is :-)
And a little comment above about subscription.
cheers
/andrej
Messages sorted by:
Reverse Date,
Date,
Thread,
Author