我正在动态生成一些正则表达式,并用应用程序中的另一个字符串事后替换匹配的结果。我正在获取匹配的开始和结束索引,然后逐个替换每个匹配的字符块,然后调整下一个匹配的偏移量。然而,在其他几个成功匹配/替换的案例中的一场比赛中,我注意到我的开始和结束索引包含一个额外的字符。
这是我用来生成正则表达式的代码:
Pattern.compile("[^a-zA-Z]+(?<match>" + Pattern.quote(search[i]) + ")[^a-zA-Z]+")
Run Code Online (Sandbox Code Playgroud)
在这种情况下添加额外的字符
search[i] = "on a daily basis"
Run Code Online (Sandbox Code Playgroud)
得到的正则表达式
[^a-zA-Z]+(?<match>\Qon a daily basis\E)[^a-zA-Z]+
Run Code Online (Sandbox Code Playgroud)
这是要匹配的相关文本
to on a daily basis.
Run Code Online (Sandbox Code Playgroud)
我想要的输出是
on a daily basis
Run Code Online (Sandbox Code Playgroud)
这是我从 matcher.group("match") 获得的输出,但是当我从同一匹配器上下文调试 start() 和 end() 结果时,我分别得到 356 和 375 (这是在全文的上下文中) ),但您可以看到这两个数字之间的差异是 19,而字符串“on a daily basic”只有 16 个字符。
我假设我需要考虑 Pattern.quote 中的 \Q 和 \E?那么第三个额外的附加角色是从哪里来的呢?为什么这种情况只发生在这种模式/目标字符串的情况下?
是否还有其他不相关的原因导致我忽略的差异?
结果正如预期的那样。您没有考虑[^a-zA-Z]+模式的开头和结尾。因此,虽然实际文本的长度是16,但匹配字符串的总长度会有所不同。
虽然Matcher#group(String)会返回该组中匹配的文本,但Matcher#start()会给出完整匹配的开始索引。方法相同end()。它将在匹配字符串的最后一个索引之后给出索引 1。
如果您想获取匹配组的开始和结束索引,可以将组名称传递给start(String)andend(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"));
}
Run Code Online (Sandbox Code Playgroud)
因此,在上面的示例中,组的长度与完整匹配的长度(这就是您得到的结果)不同。