6

问题

的行为

!(pattern-list)

在参数扩展中使用时,它不像我期望的那样工作,特别是

${parameter/pattern/string}

输入

a="1 2 3 4 5 6 7 8 9 10"

测试用例

$ printf "%s\n" "${a/!([0-9])/}"
[blank]
#expected 12 3 4 5 6 7 8 9 10

$ printf "%s\n" "${a/!(2)/}"
[blank]
#expected  2 3 4 5 6 7 8 9 10

$ printf "%s\n" "${a/!(*2*)/}"
2 3 4 5 6 7 8 9 10
#Produces the behaviour expected in previous one, not sure why though

$ printf "%s\n" "${a/!(*2*)/,}"
,2 3 4 5 6 7 8 9 10
#Expected after previous worked

$ printf "%s\n" "${a//!(*2*)/}"
2
#Expected again previous worked

$ printf "%s\n" "${a//!(*2*)/,}"
,,2,
#Why are there 3 commas???

眼镜

GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)

笔记

这些是非常基本的示例,因此如果可以在答案中包含更复杂的示例和解释,那么请这样做。

如果需要更多信息或示例,请在评论中告诉我。

已经看过extglob 如何与 shell 参数扩展一起工作?,甚至评论了该特定问题的问题所在,因此请不要将其标记为骗子。

4

1 回答 1

5

形式的参数扩展${parameter/pattern/string}(其中pattern不以 a 开头)通过在与模式匹配的/变量的值中找到最左边的最长子字符串并将其替换为. 换句话说,被分解为三个部分,, 和这样parameterpatternstring$parameterprefixmatchsuffix

  1. $parameter == "${prefix}${match}${suffix}"
  2. $prefix是能够满足其他要求的最短可能字符串(即,如果可能,匹配出现在最左边的位置)
  3. $match匹配pattern并且尽可能长
  4. 任何$prefix,$match和/或$suffix可以为空

结果${parameter/pattern/string}"${prefix}string${suffix}"

${parameter//pattern/string}对于这种类型的参数扩展suffix全局替换形式(

  • 如果"${prefix}${match}" != ""

    "${parameter//pattern/string}" = "${prefix}string${suffix//pattern/string}"
    

    否则suffix=${parameter:1}

    "${parameter//pattern/string}" = "string${parameter:0:1}${suffix}//pattern/string}"
    

现在让我们逐个分析案例:

  • "${a/!([0-9])/}" --> prefix='' match='1 2 3 4 5 6 7 8 9 10' suffix=''. 事实上, '1 2 3 4 5 6 7 8 9 10'不是由单个数字组成的字符串,因此它与 pattern 匹配!([0-9])。因此,膨胀的结果是空的。

  • "${a/!(2)/}" --> prefix='' match='1 2 3 4 5 6 7 8 9 10' suffix=''. 与上面类似,'1 2 3 4 5 6 7 8 9 10'不是由单个字符 '2' 组成的字符串,因此它匹配模式!(2)。因此,膨胀的结果是空的。

  • "${a/!(*2*)/}" --> prefix='' match='1 ' suffix='2 3 4 5 6 7 8 9 10'. 子字符串 '1'与模式匹配*2*,因此它与模式匹配!(*2*)

  • "${a/!(*2*)/,}". 这里没有惊喜,所以不需要详细说明。

  • "${a//!(*2*)/}". 这里没有惊喜,所以不需要详细说明。

  • "${a//!(*2*)/,}" --> prefix='' match='1 ' suffix='2 3 4 5 6 7 8 9 10'. 然后${suffix//!(*2*)/,}展开",2,"如下。开头的空字符串suffix匹配模式!(*2*),在结果中产生一个额外的逗号。由于触发了零长度匹配特殊情况(如上所述),第一个字符suffix被强制消耗,留下了' 3 4 5 6 7 8 9 10',它与整个!(*2*)模式匹配,并替换为我们在最终结果中看到的最后一个逗号扩张。

于 2017-05-29T14:54:46.770 回答