bash - extglob 第二个“零个或多个”运算符不工作

Han*_*gon 3 shell bash wildcards variable-substitution

鉴于:

$ shopt -s extglob
$ TEST="    z abcdefg";echo ">>${TEST#*( )z*( )}<<"
>> abcdefg<<
Run Code Online (Sandbox Code Playgroud)

为什么字母“a”前有一个空格?我希望第二个*( )会匹配空间,但它并没有接缝这样做。

我期望相当于:

$ echo ">>$(echo -n "${TEST}" | perl -pe "s/^ *z *//g")<<"
>>abcdefg<<
Run Code Online (Sandbox Code Playgroud)

*( )如果我指定下一个字符(即“a”),则第二个匹配项:

$ shopt -s extglob
$ TEST="    z abcdefg";echo ">>${TEST#*( )z*( )a}<<"
>>bcdefg<<
Run Code Online (Sandbox Code Playgroud)

bash 版本: GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)

meu*_*euh 6

${TEST#...}匹配最短的字符串,即 z 后跟零个空格。你需要${TEST##...},最长的匹配。


Har*_* Mc 5

这是由于非贪婪子字符串删除与您使用的模式类型之间的相互作用。

bash 手册中

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

匹配给定模式的零次或一次出现。

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

匹配给定模式的零次或多次出现。

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

匹配给定模式的一次或多次出现。

从我最喜欢的关于 bash字符串操作的解释中,

${string#substring}

删除$substring从前面的最短匹配项$string

${string##substring}

$substring从 前面删除最长的匹配项$string

因此,当您指定 时${TEST#*( )z*( )},您是在说:“请删除具有零个或多个空格的最短子字符串, a z,然后是零个或多个空格。

匹配最后一个空格比没有它匹配要长,所以最后一个空格永远不会匹配。

为了解决这个问题,您可以使用${TEST##*( )z*( )}匹配以零个或多个空格结尾的最长前缀或${TEST#*( )z+( )}匹配以一个或多个空格结尾的最短前缀(这在功能上等同于匹配以一个空格结尾的最短前缀)。