Parameter Expansion Flags

Expansion Flags are very powerful. However they are sometimes not that easy to understand by just reading the manual. So, let's look at some examples for their usage.

If you prefer German over English, this page was originally based on a blog posting:

(#) Flag

Note, that the (#) flag and the # modifier are two different things. See Parameter Modifiers for details.

zsh% i="4*12+10"
zsh% print \"${i}\" \"${(#)i}\"
"4*12+10" ":"
zsh% ascii ":"
  ASCII 3/10 is decimal 058, hex 3a, octal 072, bits 00111010: prints as `:'
  Official name: Colon

So, calculating 4*12+10 equals 58. The ascii command tells us, that 58 is the decimal value for the : sign in ascii-encoding. That means ${(#)param} calculates the string in $param as a formula and expands the result as the corresponding character from the ascii table.

(%) Flag

This is a simple one. You get the same %-expansions as you would expect from your prompt variables:

zsh% cd /usr/src
zsh% var="%/ - %D - %% - Howdy..."
zsh% print ${(%)var}
/usr/src - 07-06-06 - % - Howdy...

(@) Flag

This flag enables you to get separate words from arrays, although double-quotes are in effect:

zsh% foo=( bar baz foo\ bar bar\ baz )
zsh% print -l "${foo}"
bar baz foo bar bar baz
zsh% print -l "${(@)foo}"
bar
baz
foo bar
bar baz

(A)/(AA) Flags

Parameter Modifiers give enable you to do direct variable assignment: ${…::=…} and the like. Now, this flag let's you do the same for arrays and associative arrays:

zsh% print -l ${(A)foo::=foo bar baz}
foo bar baz
zsh% print ${#foo}
1

Ouch, here you see the SH_WORDSPLIT issue, that was discussed on the Parameter Expansion Page. Let's use = to enable shwordsplit temporarily.

zsh% print -l ${(A)=foo::=foo bar baz}
foo
bar
baz
zsh% print ${#foo}
3

Alright, and now let's do this for associative arrays:

zsh% print -l ${(AA)=foo::=foo0 bar foo1 baz}
bar
baz
zsh% print $foo[foo0] - $foo[foo1]
bar - baz
zsh% print ${#foo}
2

(c) Flag

This is a simple one again: If used with the ${#…} modifier, it returns the length of the string you would get, if the array elements would have been joined by spaces:

zsh% foo=( bar baz foobar )
zsh% print ${(c)#foo}
14

(C) Flag

Again, simple: This flag capitalizes the first letter of every word in an array:

zsh% foo=( bar baz foobar )
zsh% print ${(C)foo}
Bar Baz Foobar

(e) Flag

This one is a beast ;-) - it enforces all forms of substitutions and expansions on the value of a parameter:

zsh% foo='$(print $ZSH_VERSION)'
zsh% print ${(e)foo}
4.3.2
zsh% foo='print ${(c)#foo}'
zsh% print ${(e)foo}
print 16

(f)/(F) Flags

These flags are short forms of ps:\n: and pj:\n:.

(f) is specially useful to read lines of files into arrays:

zsh% cat > file
Typing one line.
And another one.
zsh% foo=($(<file))
zsh% print -l $foo
Typing
one
line.
And
another
one.
zsh% foo=((f)$(<file))
zsh% print -l $foo
Typing one line. And another one.
zsh% print ${#foo}
1
zsh% foo=("$(<file)")
zsh% print -l $foo
Typing one line.
And another one.
zsh% print -l $foo[1]
Typing one line.
And another one.
zsh% print -l $foo[2]

zsh% foo=(${(f)"$(<file)"})
zsh% print -l $foo
Typing one line.
And another one.
zsh% print -l $foo[1]
Typing one line.
zsh% print -l $foo[2]
And another one.

(F) joins array elements with \n.

zsh% foo=( foo bar baz )
zsh% print ${(F)foo}
foo
bar
baz

(k)/(v) Flags

If you got an associative array, (k) returns the keys rather than the values:

zsh% declare -A foo
zsh% foo=( foo bar foz baz )
zsh% print ${foo}
bar baz
zsh% print ${(k)foo}
foo foz
zsh% print ${${(k)foo}[1]}
foo
zsh% print ${${(k)foo}[2]}
foz

Togehter with (v) you get both:

zsh% declare -A foo
zsh% foo=( foo bar foz baz )
zsh% print ${(kv)foo}
foo bar foz baz

(U)/(L) Flags

It's getting simpler again. These flags do upper/lowercase conversion:

zsh% foo=( wEirD wORDs )
zsh% print ${(U)foo}
WEIRD WORDS
zsh% print ${(L)foo}
weird words

(M) Flag

This flag is particularly useful when doing pattern matching on array elements, as it reverses the behaviour of the ${…:#…} modifier.

zsh% setopt extended_glob
zsh% print -l ${path}
/home/ft/bin
/bin
/usr/bin
/usr/local/bin
/opt/opera/bin
/usr/games
zsh% print -l ${path:#(*/)#bin[/]#}
/usr/games
zsh% print -l ${(M)path:#(*/)#bin[/]#}
/home/ft/bin
/bin
/usr/bin
/usr/local/bin
/opt/opera/bin
zsh% print -l ${(M)path:#^(*/)#bin[/]#}
/usr/games

(o)/(O) Flags

This let's you reorder arrays.

Subflags:

  • (a): The array sorting, thus (Oa) gives reverse array order.
  • (i): case insensitive
  • (n): numeric order
zsh% foo=( 03foo 01bAR 02BAZ 04baz 06bar 05Foo )
zsh% print ${(Oa)foo}
05Foo 06bar 04baz 02BAZ 01bAR 03foo
zsh% print ${(on)foo}
01bAR 02BAZ 03foo 04baz 05Foo 06bar
zsh% print ${(On)foo}
06bar 05Foo 04baz 03foo 02BAZ 01bAR

(P) Flag

This flag interprets the content of a variable as a variable name:

zsh% foo=( wEirD wORDs )
zsh% bar="foo"
zsh% print ${(L)${(P)bar}}
weird words

(q)/(Q) Flags

This adds quoting levels:

zsh% foo='This is a damn parameter!'
zsh% echo ${(q)foo}
This\ is\ a\ damn\ parameter\!
zsh% print ${(qq)foo}
'This is a damn parameter!'
zsh% print ${(qqq)foo}
"This is a damn parameter!"
zsh% print ${(qqqq)foo}
$'This is a damn parameter!'

This is needed sometimes, when you eval a parameter. The (Q) flag works in the opposite direction, it removes quoting levels.

(t) Flag

The (t) flag displays the type of a parameter.

zsh% foo='This is a damn parameter!'
zsh% print ${(t)foo}
scalar
zsh% foo=( foo bar baz )
zsh% print ${(t)foo}
array

(u) Flag

If elements of an array got the same value multiple times, this returns that value only once:

zsh% foo=(foo foo bar foo baz bar foo bar)
zsh% print ${(u)foo}
foo bar baz

(V) Flag

This is like a builtin cat -v:

zsh% foo=$'\e[35mHello World.'
zsh% print ${foo}
Hello World.
  (( The control sequence makes this 'Hello World.' appear in magenta. ))
zsh% print ${(V)foo}
^[[35mHello World.

(w)/(W) Flags

With (w) you can count words (and in connection with (s) it even let's you define how counting is done). (W) is similar, it also counts "empty" words.

zsh% foo=$'Hello World, mere mortal.'
zsh% print ${(w)#foo}
4
zsh% print ${(ws:,:)#foo}
2
zsh% foo=$'Hello World,, mere mortal.'
zsh% print ${(Ws:,:)#foo}
3

(X) Flag

This turns on error messages for the (Q) and (e) flags as well as pattern matching in the form of ${…#…}. I didn't understand this flag correctly myself, but Bart Schaefer enlightened me in zsh-users #10451:

zsh% foo="two ' matched ' quotes"
zsh% print ${(Q)foo}
two matched quotes
zsh% foo="only one ' quote"
zsh% print ${(Q)foo}
only one ' quote
zsh% print ${(XQ)foo}
zsh: unmatched '

(z) Flag

…splits scalars using the shall parser:

zsh% foo="bar\ baz beer booze"
zsh% print ${${(z)foo}[2]}
beer

(j:...:) Flag

This joins array elements.

zsh% foo=(foo bar baz)
zsh% print ${(j:.:)foo}
foo.bar.baz
zsh% print ${(j:_-_:)foo}
foo_-_bar_-_baz

(s:...:) Flag

The opposite of (j:…:), it splits a scalar into a list.

zsh% foo="foo_-_bar_-_baz"
zsh% print -l ${(s:_-_:)foo}
foo
bar
baz

(l:expr::string1::string2:) Flag

Pad a string on the left side:

zsh% foo="foo"
zsh% bar="foo bar baz"
zsh% for i in foo bar ; do var="$i" ; print ${(l:20::.::/:)${(P)var}} ; done
................/foo
......../foo bar baz

(r:expr::string1::string2:) Flag

Pad a string on the right side:

zsh% foo="foo"
zsh% bar="foo bar baz"
zsh% for i in foo bar ; do var="$i" ; print ${(r:20::.:: :)${(P)var}} ; done
foo ................
foo bar baz ........

(p) Flag

(p) works with (j), (s), (l) and ®. It recognizes the escape sequences know by the print builtin.

zsh% foo="bar
beer
booze"
zsh% print ${(s:\n:)foo} ;: this will not work
bar
beer
booze
zsh% print ${(ps:\n:)foo} ;: this will
bar beer booze

(S) Flag

  • only makes sense in these expressions: ${…#…}, ${…%…}, ${…/…} and the like.

Searches/removes are not nailed down to the start/end:

zsh% string="Hampelmann Pampelmannnnnnn-"
zsh% print ${(S)string#am*lmann}
H Pampelmannnnnnn-
zsh% print ${(S)string##am*lmann}
Hnnnnn-
zsh% print ${(S)string%e*n}
Hampelmann Pampnnnnnn-
zsh% print ${(S)string%%e*n}
Hampelmann Pamp-

(I) Flag

  • only makes sense in these expressions: ${…#…}, ${…%…}, ${…/…} and the like.

Enhances the (S) Flag; searches for the n-th match. Example from the manual page:

zsh% string="which switch is the right switch for Ipswich?"
zsh% for i in {1..4} ; do print ${(SI:${i}:)string#w*ch} ; done
  switch is the right switch for Ipswich?
which s is the right switch for Ipswich?
which switch is the right s for Ipswich?
which switch is the right switch for Ips?

(B)/(E)/(M)/(N)/(R) Flags

These flags affect the (S) flag.

  • (B) shows the position, where the matched part starts.
  • (E) same as (B), but shows the position of the end.
  • (M) displays the matched part.
  • (N) displays the length of the matched part.
  • (R) displays the non-matching part.
zsh% string="Hampelmann"
zsh% print -l ${(SBEMNR)string#am*lmann} ${(SB)string#am*lmann} \
  ${(SE)string#am*lmann} ${(SM)string#am*lmann} ${(SN)string#am*lmann} \
  ${(SR)string#am*lmann}
ampelmann H 2 11 9
2
11
ampelmann
9
H
 
scripting/paramflags.txt · Last modified: 2010/01/05 09:20 (external edit)