我正在动态生成一些正则表达式,并在我的应用程序中使用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?但那么第三个额外的角色来自哪里呢?为什么这只出现在这种模式/目标字符串的情况下呢?
是否还存在其他一些与我无法忽视的差异无关的原因?
答案 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"));
}
所以在上面的例子中,组的长度与完全匹配的长度不同(这是你得到的结果)。