0

Suppose you have something like:

$ a=(fooa foob foox)                                    

Then you can do:

$ b=(${(M)a:#*(a|b)}) 

To select a's elements matching the pattern.

So you have:

$ print ${(qq)b}
'fooa' 'foob'

Then you expect to build the pattern in some dynamic way, so you have it in another variable, say:

$ p="*(a|b)"

And you expect this:

$ b=(${(M)a:#$p})    

Would work the same as before, as the documentation says, but it doesn't:

$ print ${(qq)b} 
''

Why is that?

Pablo Lalloni
  • 2,615
  • 19
  • 20

1 Answers1

0

Because zsh tries to select $p's value literally (a plain string text) in this case:

a=('*(a|b)' fooa foob)
p="*(a|b)"
b=(${(M)a:#$p})
print ${(qq)b}
;#⇒'*(a|b)'

We could tell zsh to treat $p's expansion as patterns rather than literal values explicitly by a ${~spec} form.

${~spec}

Turn on the GLOB_SUBST option for the evaluation of spec; if the ‘~’ is doubled, turn it off. When this option is set, the string resulting from the expansion will be interpreted as a pattern anywhere that is possible, such as in filename expansion and filename generation and pattern-matching contexts like the right hand side of the ‘=’ and ‘!=’ operators in conditions.

-- zshexpn(1): Expansion, Parameter Expansion

In this case, we could use it like this:

a=(fooa foob foox)
p="*(a|b)"
b=(${(M)a:#${~p}}) ;# tell zsh treat as a pattern for `$p`
print ${(qq)b}
;#⇒'fooa' 'foob'

Note: It gives some hints in the parameter expansion flag b for storing patterns in variable values:

b

Quote with backslashes only characters that are special to pattern matching. This is useful when the contents of the variable are to be tested using GLOB_SUBST, including the ${~...} switch.

Quoting using one of the q family of flags does not work for this purpose since quotes are not stripped from non-pattern characters by GLOB_SUBST. In other words,

   pattern=${(q)str}
   [[ $str = ${~pattern} ]]

works if $str is ‘a*b’ but not if it is ‘a b’, whereas

   pattern=${(b)str}
   [[ $str = ${~pattern} ]]

is always true for any possible value of $str.

-- zshexpn(1): Expansion, Parameter Expansion, Parameter Expansion Flags

hchbaw
  • 4,894
  • 18
  • 16