在Regex101上测试
我的测试字符串是:123456789D123456789
.{1,5}匹配12345
{1,5}?比赛1
我对两场比赛都很好.
.{1,5}?D匹配56789D !!我希望它能匹配9D
谢谢你澄清这一点.
解决方法
正则表达式引擎从左到右分析字符串.因此,它搜索符合模式的第一个字符,然后,一旦找到匹配的子字符串,就会将其作为匹配项返回.
让我们看看它是如何解析字符串的.{1,5} D:1被发现并且D被测试.发现1之后没有D,正则表达式引擎扩展惰性量词并匹配12并尝试匹配D.在2之后有3,再次,引擎扩展懒点并执行5次.在扩展到最大值之后,它看到有12345并且下一个字符不是D.由于引擎达到最大限制量词值,匹配失败,测试下一个位置.
同样的情况发生在最多5个位置.当引擎达到5时,它会尝试匹配5D,失败,尝试56D,567D,5678D – 再次失败,当它尝试匹配56789D – 宾果! – 找到匹配.
这清楚地表明,模式开头的一个延迟量化的子模式默认情况下会“贪婪”,也就是说,它与最短的子字符串不匹配.
这是regex101.com的可视化:
现在,这是一个有趣的事实:.{1,5}?在模式的末尾将始终匹配1个字符(如果有的话)因为要求至少匹配1,并且返回有效匹配就足够了.所以,如果你写D.{1,5}?
,你将得到123456789D12345D678904中的D1和D6.
有趣的事实2:在.NET中,您可以“请求”正则表达式引擎在RightToLeft修饰符的帮助下从右到左分析字符串.然后,使用.{1,5}?D,您将得到9D,见this demo.
有趣的事实3:在.NET中,(?< =(.{1,5}?))如果123456789D作为输入传递,D将把9捕获到组1中.这是因为lookbehind is implemented in .NET regex的方式(.NET反转字符串以及lookbehind内的模式,然后尝试匹配反向字符串上的单个模式).在Java中,5}))D(贪婪版本)将捕获9,因为它尝试范围内的所有可能的固定宽度模式,从最短到最长,直到一个成功. 一个解决方案是:如果你知道你需要1个字符后跟D,那就用吧
/.D/