Bash

bash - extglob 第二個“零或多個”運算符不工作

  • June 28, 2017

鑑於:

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

為什麼字母“a”之前有一個空格?我希望第二個*( )會匹配空間,但它並沒有接縫這樣做。

我期望相當於:

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

*( )如果我指定下一個以下字元(即“a”),則第二個匹配:

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

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

${TEST#...}匹配最短的字元串,即 z 後跟零個空格。你需要${TEST##...},最長的匹配。

這是由於非貪婪子字元串刪除和您使用的模式類型之間的相互作用。

bash 手冊中,

?(pattern-list)

匹配給定模式的零次或一次出現。

*(pattern-list)

匹配給定模式的零次或多次出現。

+(pattern-list)

匹配給定模式的一次或多次出現。

從我最喜歡的關於 bash字元串操作的解釋中,

${string#substring}

$substring刪除 的前面的最短匹配項$string

${string##substring}

$substring從 的 前面刪除最長的匹配項$string

因此,當您指定 時${TEST#*( )z*( )},您是在說:“請刪除具有零個或多個空格的最短子字元串 a z,然後是零個或多個空格。

最後一個空格的匹配比沒有它的匹配要長,所以最後一個空格永遠不會匹配。

為了糾正這個問題,您可以使用${TEST##*( )z*( )}匹配以零個或多個空格結尾的最長前綴,或者${TEST#*( )z+( )}匹配以一個或多個空格結尾的最短前綴(這在功能上等同於匹配以一個空格結尾的最短前綴)。

引用自:https://unix.stackexchange.com/questions/373720