当前位置: 代码迷 >> java >> 匹配正则表达式中最长的字符串或在公共子字符串的情况下
  详细解决方案

匹配正则表达式中最长的字符串或在公共子字符串的情况下

热度:20   发布时间:2023-07-17 20:32:09.0

在正则表达式 OR 中,当有多个具有公共前缀的输入时,正则表达式将匹配Regex OR中的第一个输入,而不是最长匹配。

例如,对于正则表达式regex = (KA|KARNATAKA)input = KARNATAKA ,输出将是 2 个匹配match1 =KAmatch2 = KA

但是我想要的是在Regex OR在我给定的示例中是match1 = KARNATAKA中的给定输入之外的完整最长可能匹配。

所以我现在正在做的是,我正在按长度降序对Regex OR的输入进行排序。

我的问题是,我们可以在正则表达式本身中指定匹配最长的字符串吗? 还是排序是唯一的方法?

您可以使用单词边界( \\b )来避免匹配前缀

对于您提到的情况:以下正则表达式仅匹配KAKARNATAKA

(\bKA\b|\bKARNATAKA\b)

您可以为此创建一个辅助方法:

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 这仅适用于没有嵌套括号的简单表达式。 如果您期望更复杂的表达式,则需要进行调整。