java 正则长度_重访:Java正则表达式中的零长度匹配

我去年在看这个问题:Java Regex中的零长度匹配:

Pattern pattern = Pattern.compile("a?");

Matcher matcher = pattern.matcher("ababa");

while(matcher.find()){

System.out.println(matcher.start()+"["+matcher.group()+"]"+matcher.end());

}

产生输出:

0[a]1

1[]1

2[a]3

3[]3

4[a]5

5[]5

我想知道这是否正确。该模式匹配" a"或空字符串。当Matcher指向第一个" b"时,就没有" a",因此find()匹配空字符串。

但是,javadoc说:

This method starts at the beginning of this matcher's region, or, if a

previous invocation of the method was successful and the matcher has

not since been reset, at the first character not matched by the

previous match.

因此,当Matcher指向'b'时,不会匹配任何字符,并且find()会匹配一个空字符串,这意味着在此之后,与上一个匹配项不匹配的第一个字符(即空字符串)仍为'b '。根据以上所述,这应该意味着下一个find()应该在同一位置开始,这意味着代码应该无限循环。但这当然不是正在发生的事情。看起来当匹配空字符串时,它只是将起始点提高了1。

那么这是什么一回事?实现是错误的,还是javadoc遗漏了一些东西,还是我遗漏了一些东西?

不," b"与" a?"不匹配。 从输出1 [] 1可以看出,开始和结束是相同的,因此它是空匹配。 但是,在那种情况下,find()已消耗了" b"。 ajb提出的问题是为什么在这种情况下find()会不断向前发展。 答案是匹配的组与匹配的区域不同(也尝试打印matcher.regionEnd())。

它仍然没有道理。 在与第一个" a"匹配之后,其指向b。 然后,第二个find()返回空字符串,并且根据JLS,匹配器仍应指向下一个find()的b,因为第二个find()不匹配b。 因此,在我看来,匹配器在第二个find()之前应与第三个find()之前处于相同状态……但由于返回的结果不同,所以匹配有所不同。 regionStart()和regionEnd()都不会更改(我认为它们仅由region()更改)。 那有什么不同呢?

好的,当find()返回一个空字符串时,确实有一种特殊情况。为了明确起见,由于我认为有些人不理解该问题,因此我的问题是,为什么匹配器状态在第二个find()之前和第三个find()之前应该不同,因为"第一个字符与上一个字符不匹配"匹配"在两种情况下都相同。

区别在于,上一个匹配项的边界存储在匹配器的状态中,并且确实会影响下一个find(),但仅在这种情况下。从Matcher.java中的find()代码中:

int nextSearchIndex = last;

if (nextSearchIndex == first)

nextSearchIndex++;

除非最后一个find()返回一个空字符串(或者其他方法设置了first或last),否则last是开始搜索的地方,然后将其向上移动一个。这个代码段没有评论,所以我不确定目的是什么,但是看起来它是故意作空字符串匹配的特殊情况。不过,它似乎确实与javadoc矛盾,因为在这种情况下,搜索从javadoc声明的位置之外的其他地方开始。

编辑:顺便说一句,这的确有可能令人惊讶的结果:

Pattern p = Pattern.compile("a?");

Matcher m = p.matcher ("abcde");

m.find();

System.out.println("[" + m.group() +"]");

m.find();

System.out.println("[" + m.group() +"]");

m.usePattern (Pattern.compile("[bd]"));

m.find();

System.out.println("[" + m.group() +"]");

输出

[a]

[]

[d]

最后一个匹配项找不到" b",即使" b"字符??没有被任何先前的匹配项匹配,也不应该被跳过。不过,它有点晦涩。

a?表示零个或一个'a'字符,因此它将与a或" nothing"匹配-与位于" a"和" b"字符??之间的" a"字符和"虚无"匹配。

这是完全正确和预期的。

这是正确的,但缺少一个重要的额外细节。 默认情况下,正则表达式配置为贪婪,这意味着它将扩展以匹配最大可能的模式。 因此,即使0[]0应该在匹配列表中,也不会得到报告,因为0[a]1是在相同索引处的较大匹配。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值