【问题标题】:Match longest string in Regex OR in case of common substring匹配正则表达式中的最长字符串或在常见子字符串的情况下
【发布时间】:2019-02-21 05:46:45
【问题描述】:

在正则表达式 OR 中,当有多个输入具有公共前缀时,正则表达式将匹配 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 中的输入进行排序。

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

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

【问题讨论】:

  • 试试这个\b(KA|KARNATAKA)\b
  • @SHAHAKASH 如果他想匹配KARNA 怎么办。您的解决方案 \b(KA|KARNA)\b 在那里不起作用
  • 是什么问题阻止您进行排序?
  • @Jai 当输入非常少或者是一次性工作时,对输入进行排序是没有问题的。当我们有大量输入并且我们必须一次又一次地动态地进行时,就会出现性能问题。我只是想知道我们是否可以让Regex engine 处理这个问题。
  • 尝试使用单词边界\b(\bKA\b|\bKARNATAKA\b) 会起作用

标签: java regex regex-greedy


【解决方案1】:

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

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

(\bKA\b|\bKARNATAKA\b)

Try here

【讨论】:

  • 如果他想匹配KARNA怎么办。您的解决方案 (\bKA\b|\bKARNATAKA\b) 在评论中不起作用。
  • @SHAHAKASH 它应该匹配“KARNA”。
  • 他想要最长的匹配。
  • @SHAHAKASH 最长精确匹配。
  • if String test="KA KARN" --> 那么他想要的是 KARN,而不是 KA,如果我没记错的话,这是个问题。
【解决方案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

附:这仅适用于没有嵌套括号的简单表达式。如果您期待非常复杂的表达式,则需要进行调整。

【讨论】:

    猜你喜欢
    • 2018-05-04
    • 2011-11-08
    • 2012-03-02
    • 1970-01-01
    • 1970-01-01
    • 2022-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多