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

Re: how to force scalar to be an array?

On Sat, 28 Aug 2004, Andy Spiegl wrote:

> > So your only safe bet is to actually assign the scalar to an array, and
> > then use subscripting on the array.
> But then how would I be able to split the words if there are more than one?

What I meant was:

	words=( $=result )
	print $words[1]

You can even do it in one expression:

	print ${${(A)=words::=$result}[1]}

Note that you have to put the splitting flag on the LEFT side of ::= or 
you don't get the array behavior from the subscript when there is only one 
element.  That works with the (s) parameter flag and its relatives, too;

	print ${${(As:,:)words::=chop,split,slice}[1]}
	print ${${(As:.:)words::=chop,split,slice}[1]}

> Hm, I think I must be doing something wrong here.  Shouldn't it be an 
> absolutely easy and common task to split a line into its words and then 
> pick the first one and the rest of them.

Yes, you'd think so, but it's been zsh's behavior for a long time to treat 
a one-element array as a scalar in certain contexts.  You'd also think 
that the (@) flag would fix that, but it only *preserves* array-ness in 
the transition from inner to outer nested expansions, it doesn't *create*
array-ness from a scalar.

The latter might be something we could consider changing without much risk
of breaking anything.

> In Perl I'd do for example: (just to illustrate what I want to do)
>  $result=`some_proggie`
>  @words = split (/\s/, $result);
> or maybe:
>  $result =~ /(\S+)(.*)/;
>  $first_word=$1;
>  $rest_words=$2;

You can do that latter one in zsh, too, if you have extendedglob set:

	: ${result//(#b)([^[:space:]]#)(*)/}
	print -l $match[1] $match[2]

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