![为什么正则表达式 [0-9]{0,2} 在 sed 中不贪婪?](https://linux22.com/image/157533/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%20%5B0-9%5D%7B0%2C2%7D%20%E5%9C%A8%20sed%20%E4%B8%AD%E4%B8%8D%E8%B4%AA%E5%A9%AA%EF%BC%9F.png)
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 =
当然,这不可能出现在任何线路。