为什么正则表达式 [0-9]{0,2} 在 sed 中不贪婪?

为什么正则表达式 [0-9]{0,2} 在 sed 中不贪婪?
echo '123980925sriten34=ienat' | sed -e 's/^.*\?\([1-9][0-9]\{0,2\}\+\)\([%=+-]\).*/ \1 \2 /'

正在给出结果:

 4 =

我期待:

 34 =

我不明白什么?

(哦,我什至添加了+?来双重确定,但据我所知,{0,2}没有它们应该会贪婪。)

答案1

问题,正如 Steeldriver 所说,这不是[0-9]{0,2}非贪婪的吗?问题在于它.*?之前是贪婪的。  sed 支持BRE和ERE,两者都不支持非贪婪匹配。这是 PCRE 的一个特点。例如,以下命令:

$ echo 'aQbQc' | sed    's/.*\?Q/X/'
$ echo 'aQbQc' | sed    's/.*Q/X/'
$ echo 'aQbQc' | sed -r 's/.*?Q/X/'
$ echo 'aQbQc' | sed -r 's/.*Q/X/'

所有输出

Xc

(我不确定为什么它会忽略?。)

与 SED 正则表达式的非贪婪匹配(模拟 perl 的.*?

您对要执行的功能的描述很肤浅,但我相信我已经对其进行了逆向工程。您可以通过以下方式获得想要的效果 不匹配找到该号码之前要匹配的号码之前的字符:

$ echo '123980925sriten34=ienat' | sed -e 's/\([1-9][0-9]\{0,2\}\+\)\([%=+-]\).*/! \1 \2 /' -e 's/.*!//'
 34 =

将 替换!为已知不会出现在输入数据中的任何字符串。如果您没有这样的字符串,但您使用的是 GNU sed,则可以使用换行符:

$ echo '123980925sriten34=ienat' | sed -e 's/\([1-9][0-9]\{0,2\}\+\)\([%=+-]\).*/\n \1 \2 /' -e 's/.*\n//'
 34 =

当然,这不可能出现任何线路。

相关内容