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

Re: trying to understand scalar subscripting



Sebastian Stark wrote:
> Fist I set aaa to some scalar value and print it:
> 
> 	% aaa="fasdf gaag sdlkfjh dsfsags"
> 	% print -l $aaa
> 	fasdf gaag sdlkfjh dsfsags
> 
> That was expected. Now I expand all elements of the parameters:
> 
> 	% print -l $aaa[*]
> 	fasdf gaag sdlkfjh dsfsags
> 
> Okay, not quite expected. I thought this would print all the  
> characters in aaa in a separate line each. But this still does not  
> confuse me enough. So I try a subscript range:
> 
> 	% print -l $aaa[1,3]
> 	fas
> 
> This was kind of expected.

This is the same function as the previous one, except [*] is like
[1,-1].  Subscripting doesn't imply splitting; it's basically a
substring operation.  You can split into individual characters, as a
special case, with a flag to the whole parameter, ${(s::)aaa}.
${(s::)aaa[1,3]} also works.

> Now I try to use the w and s:: subscript  
> flags. zshparam(1) says they should work with scalars:
> 
> 	% print -l $aaa[(ws:a:)1,3]
> 	fas
> 
> Hm. I thought that would do word splitting because of (w) and also  
> use ,a` as the separator instead of , `.

The key thing to remember is the flags *only* apply to the subscript,
not the parameter as a whole, which is why this notation is different
from the parameter flag notation.

Here, it's using "a" as the separator just to find array index 1.
That's at the start of the string, so you get the same as if you hadn't
used (ws:a:).  Then the 3 is normal (the flags don't apply to it,
they're applied to each subscript separately).

Suppose you'd picked (let's skip the -l, I've already explained the
parameter itself isn't being split):

% print $aaa[(ws:a:)2,(ws:a:)3]
sdf gaag sdlkfjh dsfs

What you've got here is the parameter from the position where the start
of the second array element would have been (if the scalar was split on
a) to the position where the end of the third array element would have
been.  (The "aa" produces a null element which is ignored, so acts the
same as "a".)

> But what really confuses me  
> is this:
> 
> 	% print -l $aaa[(ws:a:)*]
> 	zsh: bad math expression: operand expected at `*'
> 
> Huh? One could say what I am doing is completely silly, but when I try  
> to do this with a real array I get the same error message:
> 
> 	% bbb=(fasdf gaag sdlkfjh dsfsags)
> 	% print -l $bbb[(ws:a:)*]
> 	zsh: bad math expression: operand expected at `*'

Again, the operation (splitting) you're doing is simply for the purpose
of finding the subscript.

For this reason, only a numeric subscript is useful.  The example
$aaa[(ws:a:)*] says something like "split into words on 'a' to find the
subscript and then give me the position you get from subscript... er,
hang on a minute, I've changed my mind, give me the entire parameter".
This naturally confuses it.

Trying to do it on an array doesn't change matters:  the flag operates
only on a scalar, so it will (I think) concatenate the array then do the
same thing, but again only for the purpose of finding the subscript.  (I
haven't actually been moved to check this, the point is it *still*
doesn't do what you originally thought any more than it did before.)

If what you want to do is split the string, then as Mikael said you need
to use the parameter flag ${(s:a:)aaa}.  This now splits into real live
words.  You'll find

print -l ${(s:a:)aaa}

does what you expect.  You've now got a real array expression and the
nested syntax Mikael referred to works on it.

The flags for handling subscripts in this way have a fairly limited use.
I can't offhand think of a reason for using them.  Almost certainly
splitting into a proper array and indexing that is more useful and less
confusing.

-- 
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



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