【问题标题】:Why this expansion inside expansion pattern doesn't work?为什么这种内部扩展模式的扩展不起作用?
【发布时间】:2017-01-10 19:59:33
【问题描述】:

假设你有类似的东西:

$ a=(fooa foob foox)                                    

那么你可以这样做:

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

选择与模式匹配的元素。

所以你有:

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

然后您希望以某种动态方式构建模式,因此您将它放在另一个变量中,例如:

$ p="*(a|b)"

而你期望这样:

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

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

$ print ${(qq)b} 
''

这是为什么呢?

【问题讨论】:

    标签: shell scripting zsh variable-expansion


    【解决方案1】:

    因为在这种情况下 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-03
      • 1970-01-01
      • 2011-07-17
      • 2015-11-29
      相关资源
      最近更新 更多