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



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

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

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 basisE)[^a-zA-Z]+

这是要匹配的相关文本

to on a daily basis.

我想要的输出是

on a daily basis

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

假设我需要考虑 Pattern.quote 中的 \Q 和 \E?但是,第三个额外的附加字符从何而来?为什么这只发生在这种模式/目标字符串的情况下?

是否存在我忽略了其他不相关的差异原因?

结果符合预期。您没有考虑模式开始和结束时的[^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")); 
}

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

最新更新