请解释此正则表达式的输出(以正向先行为开头)

3
Pattern p = Pattern.compile("(?=[1-9][0-9]{2})[0-9]*[05]");
Matcher m = p.matcher("101");
while(m.find()){
    System.out.println(m.start()+":"+ m.end()+ m.group());
}

输出------ >> 0:210

请告诉我为什么在这里m.group()的输出是10。 据我所知,m.group()应该返回空,因为[05]与任何内容都不匹配。


你为什么这样认为?你没有在 [05] 后设置 ?? 量词。它必须匹配某些内容。 - Wiktor Stribiżew
4个回答

2
你的Pattern,(?=[1-9][0-9]{2})[0-9]*[05],由两部分组成:
(?=[1-9][0-9]{2})

并且

[0-9]*[05]

第一部分是一个零宽度正向先行断言,它搜索长度为3的数字,第一个不能是0。这与你的101匹配。 第二部分搜索任意数量的数字,然后是0或5。这与101的前两个字符匹配,因此结果是10
有关更多信息,请参见Java - Pattern

2
@Neftas 第一部分将匹配长度为3的数字。 - Manu

0

你的正则表达式正在寻找以下内容:

  • [1-9]: 匹配列表中出现的单个字符 1-9:介于1和9之间的单个字符
  • [0-9]{2}: 匹配列表中出现的单个字符 量词:{2} 恰好2次 0-9:介于0和9之间的单个字符
  • [0-9]*: 匹配列表中出现的单个字符 量词:* 重复零次或更多次,尽可能多地返回所需内容[贪婪模式] 0-9:介于0和9之间的单个字符
  • [05]: 匹配列表中出现的单个字符 05:列表中的单个字符05

对于字符串“101”,这匹配了前两个字符101, 因此你要打印输出:

System.out.println(**m.start()**+":"+ **m.end()**+ m.group());

其中m.start()返回前一个匹配的起始索引(字符0)。m.end()返回最后一个匹配字符之后的偏移量。而m.group()返回前一个匹配的输入子序列。


1
那怎么回答它为什么与“101”匹配呢? - Manu
先生,很抱歉我仍然不明白为什么m.group()返回10。 - user3907559
在lookaround表达式之后,[0-9]*匹配101,然后尝试匹配[05],但不匹配,所以为什么m.group(0)返回10。如果我假设101失败,则它回溯到10,然后再次尝试匹配[05],在那里它再次失败,并进行进一步的回溯。请解释输出结果。 - user3907559
因为10是由正则表达式匹配到的字符串。@user3907559 - ΦXocę 웃 Пepeúpa ツ
@user3907559,你已经接近成功了。它将再次回溯一次,直到[0-9]*仅匹配1,然后[05]将匹配0,因此输出为10 - Stefan van den Akker
只是提醒你,有一些相当强大的在线正则表达式工具。我个人使用 regex101,它可以突出显示捕获组并让您设置单元测试。这是您的正则表达式示例:https://regex101.com/r/dM8tW0/1 - SlopeOak

0

这个正则表达式的目的是匹配一个大于或等于100的5的倍数,但如果没有锚点就毫无用处。应该改为:

^(?=[1-9][0-9]{2}$)[0-9]*[05]$

锚点可以确保前瞻和主体部分都检查整个字符串。但是该任务无需前瞻,这样也可以正常工作:
^[1-9][0-9][05]$

0

正如@AlanMoore所说,必须有一种对齐方式。

断言是一个自包含的实体,它们只需通过即可
进入下一构造。

让我们看看(?=[1-9][0-9]{2})匹配的内容;

1111111110666
2222222222222222225666
33333333333333333333333330666

到目前为止还不错,进入下一个构造。

让我们看看[0-9]*[05]匹配什么。
无论这个匹配是什么都是最终答案。

1111111110666
2222222222222222225666
33333333333333333333333330666

要学会的是,为了得出一个有凝聚力的答案,必须制定与
后面的结构相一致的断言。

这是一个可以应用于断言之后的约束条件示例。

该断言需要三个数字,第一个数字必须大于等于1。
在断言之后的结构中,它可以是任意数量的数字,只要以0或5结尾即可。

最后一部分令人不安,因为它只匹配500000。

所以,你至少需要三个数字。
可以这样做:

[0-9]{2,}[05]

这表示两件事:

  1. 至少有三个数字,但可以更多
  2. 它必须以0或5结尾

就是这样,把它们放在一起,就是:

(?=[1-9][0-9]{2})[0-9]{2,}[05]

当然,这可以简化为:

[1-9][0-9]+[05]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接