1

I have to split a string and use a part of it for further processing. So the idea is:

string='aaa-bbb-ccc-ddd'
parts=(${(@s:-:)string})
print -- $parts[3]
# ccc

I would like to refactor the second and third line into one, however

print -- (${(@s:-:)string})[3]

does not work because of 'bad pattern' error. Also

print -- ${(${(@s:-:)string})[3]}

is wrong, since in this case the array expression is interpreted a flags. Even print -- (${(@s:-:)string}) does not work. I suspect that the expression that creates the array is not evaluated in pace. Could someone please explain and point me in the right direction?

asked Dec 10, 2025 at 9:49

2 Answers 2

2

The parentheses in var=(<expr>) are really part of the assignment and not the expansion, so they are not included in a nested expression. Try this:

print -r -- ${${(s:-:)string}[3]}
#=> ccc

Note that in zsh arrays, empty unquoted values are omitted from an expansion. Empty values can be included by using quotes and the (@) parameter expansion flag:

#!/usr/bin/env zsh
# With the double dash, split[2] will be empty:
local string='aaa--bbb-ccc-ddd'
local -a split=( "${(@s:-:)string}" )
typeset -p split
#=> typeset -a split=( aaa '' bbb ccc ddd )
split=( ${(s:-:)string} )
typeset -p split
#=> typeset -a split=( aaa bbb ccc ddd )
print -r -- ${"${(@s:-:)string}"[3]}
#=> bbb
print -r -- ${${(s:-:)string}[3]}
#=> ccc
answered Dec 10, 2025 at 14:32
Sign up to request clarification or add additional context in comments.

2 Comments

Ah interesting, so the problem is really that I tried produce an array. However, your second example does not work for me in zsh 5.9. It print "a" instead of "ccc".
Doh - swapped some lines in my test script. I deleted that section.
1

For completeness, besides ${${(s[-])string}[3]}, which splits on - to get a list and then takes the 3rd element from that list, you can use:

$ string=aaa-bbb-ccc
$ print -r - $string[(ws[-])3]
ccc

Which uses the w subscript flag to index a string word-wise instead of the default of character-wise, and the s subscript flag to specify how those words are separated.

In that case, there's however no @ flag you can use to preserve empty elements. -aa---bb-cc- has 3 and only 3 -separated words, aa, bb and cc.

answered Dec 23, 2025 at 16:03

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.