我正在动态生成一些正则表达式,并将匹配的结果替换为应用程序中的另一个事后字符串。我正在获取匹配项的开始和结束索引,然后逐个替换每个匹配的字符块,然后调整下一场匹配项的偏移量。但是,在其他几个成功匹配/替换的案例中的一个匹配中,我注意到我的开始和结束索引包含一个额外的字符。
这是我用来生成正则表达式的代码:
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"));
}
因此,在上面的例子中,组的长度与完全匹配的长度不同(这就是你得到的结果)。