为什么扩展模式内的这种扩展不起作用?

时间:2017-01-10 19:59:33

标签: shell scripting zsh variable-expansion

假设你有类似的东西:

$ a=(fooa foob foox)                                    

然后你可以这样做:

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

选择与模式匹配的元素。

所以你有:

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

然后你希望以某种动态方式构建模式,所以你将它放在另一个变量中,比如说:

$ p="*(a|b)"

你期待这个:

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

正如文档所述,它将像以前一样工作,但它不会:

$ print ${(qq)b} 
''

为什么?

1 个答案:

答案 0 :(得分:0)

因为在这种情况下zsh试图逐字地选择$p的值(纯字符串文本):

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

我们可以告诉zsh将$p的扩展视为模式而不是${~spec}形式明确的文字值。

  

$ {〜规范}

     

启用GLOB_SUBST选项以评估规范;如果“~”加倍​​,请将其关闭。设置此选项后,扩展产生的字符串将被解释为任何可能的模式,例如文件名扩展和文件名生成以及模式匹配上下文(如“=”的右侧)条件中的'!='运营商。

     

- zshexpn(1): Expansion, Parameter Expansion

在这种情况下,我们可以像这样使用它:

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

注意:它在参数扩展标志b中提供了一些提示,用于在变量值中存储模式:

  

b

     

使用反斜杠引用仅对模式匹配特殊的字符。当使用GLOB_SUBST(包括${~...}开关)测试变量的内容时,此功能非常有用。

     

使用q系列标志之一进行引用不能用于此目的,因为引号不会被GLOB_SUBST从非模式字符中删除。换句话说,

   pattern=${(q)str}
   [[ $str = ${~pattern} ]]
     如果$str为“a*b”,则

有效,但如果为“a b”则无效,而

   pattern=${(b)str}
   [[ $str = ${~pattern} ]]
     对于$str的任何可能值,

始终为真。

     

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