匹配正则表达式中的最长字符串,或者在使用公共子字符串时匹配

时间:2019-02-21 05:46:46

标签: java regex regex-greedy

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

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

但是我想要的是与Regex OR中给定输入(在给定示例中为match1 = KARNATAKA)中的最长可能的完全匹配。

Here is the example in a regex client

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

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

I have already refered this question and I don't see a solution other than sorting

2 个答案:

答案 0 :(得分:1)

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

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

(\bKA\b|\bKARNATAKA\b)

Try here

答案 1 :(得分:0)

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

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

P.S。这仅适用于没有嵌套括号的简单表达式。如果您期望复杂的表达式,则需要进行调整。