Flags let zsh do in one expansion what bash needs loops or external tools for.
Zsh puts flags in parentheses right after the opening brace: ${(flags)name}. Several can be combined and expansions nest, with the inner result feeding the outer one.
- Split and join:
(s:,:)splits on a string,(f)splits on newlines (the most common way to turn command output into an array),(j:,:)joins with a separator,(F)joins with newlines. - Case:
(U)upper,(L)lower,(C)capitalise words. - Order and uniqueness:
(o)sort ascending,(O)descending,(n)numeric sort,(u)unique. - Associative arrays:
(k)keys,(v)values,(kv)pairs. - Quoting:
(q)quotes the value for safe reuse as shell input,(Q)removes one level of quoting. - Indirection:
(P)treats the value as the name of another parameter. (@)keeps array elements separate inside double quotes, like"${arr[@]}".
Subscript flags search arrays: $arr[(i)value] gives the index of the first match (one past the end if missing), $arr[(r)pattern] the first matching element, (I) and (R) search from the end.
Nesting avoids temporaries: ${${f:t}%%.*} takes the base name, then strips every extension. ${:-text} creates a value from literal text, handy as the innermost expansion. Splitting with (s) drops empty fields unless the expansion is quoted with (@).
Example
csv="b,a,c,a"
parts=(${(s:,:)csv})
print $#parts # 4
print ${(j:-:)parts} # b-a-c-a
print ${(uo)parts} # a b c (unique, sorted)
print ${(U)csv} # B,A,C,A
lines=(${(f)"$(printf 'x 1\ny 2\n')"})
print $#lines # 2 (split on newlines)
fruits=(apple banana cherry)
print $fruits[(i)banana] # 2 (index of the element)
print $fruits[(i)kiwi] # 4 (not found: length + 1)
print $fruits[(r)c*] # cherry
ref=fruits
print ${(P)ref} # apple banana cherry (indirection)
f=/a/b/archive.tar.gz
print ${${f:t}%%.*} # archive (nested expansion)
s="it's here"
print -r -- ${(q)s} # it\'s\ hereRemember
- ${(s:x:)v} splits, ${(j:x:)arr} joins, (f) splits lines
- (o) (O) (u) sort and deduplicate; (k) (v) for maps
- $arr[(i)x] and $arr[(r)pat] search arrays
Watch out for
- Using plain print to show (q) output: print interprets the backslashes again; use print -r.