问题描述
在正则表达式 OR 中,当有多个具有公共前缀的输入时,正则表达式将匹配Regex OR
中的第一个输入,而不是最长匹配。
例如,对于正则表达式regex = (KA|KARNATAKA)
和input = KARNATAKA
,输出将是 2 个匹配match1 =KA
和match2 = KA
。
但是我想要的是在Regex OR
在我给定的示例中是match1 = KARNATAKA
中的给定输入之外的完整最长可能匹配。
所以我现在正在做的是,我正在按长度降序对Regex OR
的输入进行排序。
我的问题是,我们可以在正则表达式本身中指定匹配最长的字符串吗? 还是排序是唯一的方法?
1楼
您可以使用单词边界( \\b
)来避免匹配前缀
对于您提到的情况:以下正则表达式仅匹配KA
或KARNATAKA
(\bKA\b|\bKARNATAKA\b)
2楼
您可以为此创建一个辅助方法:
public final class PatternHelper {
public static Pattern compileSortedOr(String regex) {
Matcher matcher = Pattern.compile("(.*)\\((.*\\|.*)\\)(.*)").matcher(regex);
if (matcher.matches()) {
List<String> conditions = Arrays.asList(matcher.group(2).split("\\|"));
List<String> sortedConditions = conditions.stream()
.sorted((c1, c2) -> c2.length() - c1.length())
.collect(Collectors.toList());
return Pattern.compile(matcher.group(1) +
"(" +
String.join("|", sortedConditions) +
")" +
matcher.group(3));
}
return Pattern.compile(regex);
}
}
Matcher matcher = PatternHelper.compileSortedOr("(KA|KARNATAKA)").matcher("KARNATAKA");
if (matcher.matches()) {
System.out.println(matcher.group(1));
}
输出:
KARNATAKA
PS 这仅适用于没有嵌套括号的简单表达式。 如果您期望更复杂的表达式,则需要进行调整。