负参数在参数扩展中如何在extglob中工作

123*_*123 6 bash extglob parameter-expansion

问题

的行为

!(pattern-list)
Run Code Online (Sandbox Code Playgroud)

特别是在参数扩展中使用时,我的工作方式不正常

${parameter/pattern/string}
Run Code Online (Sandbox Code Playgroud)

输入

a="1 2 3 4 5 6 7 8 9 10"
Run Code Online (Sandbox Code Playgroud)

测试用例

$ 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???
Run Code Online (Sandbox Code Playgroud)

眼镜

GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)
Run Code Online (Sandbox Code Playgroud)

笔记

这些是非常基本的例子,所以如果可以在答案中包含更复杂的例子和解释,那么请做.

更多信息或示例需要在评论中告诉我.

已经看过extglob如何使用shell参数扩展?,甚至评论了这个特定问题的问题,所以请不要标记为欺骗.

Leo*_*eon 5

表单的参数扩展${parameter/pattern/string}(其中pattern不以 a 开头/)的工作方式是在parameter与模式匹配的变量值中查找最左边的最长子字符串pattern并将其替换为string。换句话说,$parameter被分解为三部分prefixmatch, 并且suffix使得

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

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

对于${parameter//pattern/string}这种类型参数扩展的全局替换形式(),对suffix部分递归执行相同的过程,但零长度匹配作为特殊情况处理(为了防止无限递归):

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

  • "${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'不是由单个数字组成的字符串,因此它与模式匹配!([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*)模式匹配,并被替换为我们在最终结果中看到的最后一个逗号扩张。