使用Java 7和java.util.regex.Pattern中的默认RegEx实现,给出这样的正则表达式:
^start (m[aei]ddel[0-9] ?)+ tail$
这样的字符串:
start maddel1 meddel2 middel3 tail
是否可以使用锚定的正则表达式获得这样的输出:
start <match> <match> <match> tail
。
我可以让每个群体都没有这样的锚:
正则表达式:m[aei]ddel[0-9]
StringBuffer sb = new StringBuffer();
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
matcher.appendReplacement(sb, Matcher.quoteReplacement("<middle>"));
}
问题在于,我正在处理一个非常大的数据集,能够锚定模式将是一个巨大的性能胜利。
然而,当我添加锚点时,我能找到的唯一API需要完整匹配并访问该组的最后一次出现。我的情况我需要验证正则表达式实际匹配(即整个匹配),但在替换步骤中我需要能够访问它自己的每个组。
编辑我想避免在单独的步骤中寻找锚点等变通方法,因为它需要对代码进行更大的更改并将其全部包装在RegExes感觉更优雅。< / p>
答案 0 :(得分:3)
您可以使用\G
:
final String regex = "(^start |(?<!^)\\G)m[aei]ddel[0-9] (?=.* tail$)";
final String str = "start maddel1 meddel2 middel3 tail";
String repl = str.replaceAll(regex, "$1<match> ");
//=> start <match> <match> <match> tail
\G
在上一场比赛结束或第一场比赛的字符串开头处断言位置。
答案 1 :(得分:2)
要一步完成,您需要使用基于\G
的正则表达式进行锚定。但是,您还需要一个积极的先行来检查字符串是否以所需的模式结束。
这是一个应该有效的正则表达式:
(^start|(?!\A)\G)\s+m[aei]ddel[0-9](?=(?:\s+m[aei]ddel[0-9])*\s+tail$)
请参阅regex demo
String s = "start maddel1 meddel2 middel3 tail";
String pat = "(^start|(?!\\A)\\G)\\s+(m[aei]ddel[0-9])(?=(?:\\s+m[aei]ddel[0-9])*\\s+tail$)";
System.out.println(s.replaceAll(pat, "$1 <middle>" ));
<强>解释强>:
(^start|(?!\A)\G)
- 在字符串末尾匹配start
或上一次成功匹配结束\s+
- 一个或多个空格m[aei]ddel[0-9]
- m
,然后a
,e
,i
,然后是ddel
,然后是1位(?=(?:\s+m[aei]ddel[0-9])*\s+tail$)
- 仅限于:
(?:\s+m[aei]ddel[0-9])*
- 零个或多个1+空格序列和middelN
模式\s+
- 一个或多个空格tail$
- tails
substring后跟字符串结尾。答案 2 :(得分:2)
使用\G
锚点,对于find
方法,您可以这样写:
pat = "\\G(?:(?!\\A) |\\Astart (?=(?:m[aei]ddel[0-9] )+tail\\z))(m\\S+)";
细节:
\\G # position after the previous match or at the start of the string
# putting it in factor makes fail the pattern more quickly after the last match
(?:
(?!\\A) [ ] # a space not at the start of the string
# this branch is the first one because it has more chance to succeed
|
\\A start [ ] # "start " at the beginning of the string
(?=(?:m[aei]ddel[0-9] )+tail\\z) # check the string format once and for all
# since this branch will succeed only once
)
( # capture group 1
m\\S+ # the shortest and simplest pattern that matches "m[aei]ddel[0-9]"
# and excludes "tail" (adapt it to your need but keep the same idea)
)