为什么java.util.regex.Matcher start()和end()在这种情况下返回额外的字符?

时间:2015-03-16 15:34:54

标签: java regex string

我正在动态生成一些正则表达式,并在我的应用程序中使用post-hoc中的另一个字符串替换匹配的结果。我正在接受匹配的开始和结束索引,然后逐个替换每个匹配的字符块,然后调整下一个匹配的偏移量。但是在其他几个成功匹配/替换的案例中,我注意到我的开始和结束索引包含一个额外的字符。

以下是我用来生成正则表达式的代码:

Pattern.compile("[^a-zA-Z]+(?<match>" + Pattern.quote(search[i]) + ")[^a-zA-Z]+")

在添加额外字符的情况下

search[i] = "on a daily basis"

由此产生的正则表达式

[^a-zA-Z]+(?<match>\Qon a daily basis\E)[^a-zA-Z]+

这是与

匹配的相关文字
to on a daily basis.

我想要的输出是

on a daily basis

这是我从matcher.group获得的输出(“匹配”),但是当我从相同的匹配器上下文调试start()和end()结果时,我分别得到356和375(这是在上下文中)全文),但你可以看到这两个数字之间的差异是19,而字符串“每天”只有16个字符。

我假设我需要考虑Pattern.quote中的\ Q和\ E?但那么第三个额外的角色来自哪里呢?为什么这只出现在这种模式/目标字符串的情况下呢?

是否还存在其他一些与我无法忽视的差异无关的原因?

1 个答案:

答案 0 :(得分:4)

结果如预期。您没有在模式的开头和结尾考虑[^a-zA-Z]+。因此,虽然实际文本的长度为16,但匹配字符串的总长度会有所不同。

虽然Matcher#group(String)会返回该组中匹配的文字,但Matcher#start()会给出完整匹配的起始索引。 end()方法也是如此。它会在匹配字符串的最后一个索引之后给出1的索引。

如果要获取匹配组的开始和结束索引,可以将组名称传递给start(String)end(String)方法。

用小字符串试试这个,你就会知道。

String search = "on a daily basis";
String toMatch = "to on a daily basis. ";
Pattern pattern = Pattern.compile("[^a-zA-Z]+(?<match>" + Pattern.quote(search) + ")[^a-zA-Z]+");

Matcher matcher = pattern.matcher(toMatch);

if (matcher.find()) {
  System.out.println(matcher.group().length());
  System.out.println(matcher.start());
  System.out.println(matcher.end());

  System.out.println(matcher.group("match").length());
  System.out.println(matcher.start("match")); // your expected result
  System.out.println(matcher.end("match")); 
}

所以在上面的例子中,组的长度与完全匹配的长度不同(这是你得到的结果)。