在Java中,如何从特定的正则表达式创建所有可能数字的列表?

2022-09-04 04:18:42

我有一个奇怪的问题,至少一个我从未遇到过的问题。我有一个前提条件,客户有与标签关联的简单正则表达式。标签是他们所关心的。我想做的是创建一个列表,其中包含与这些正则表达式中的每一个匹配的所有可能数字。我会有逻辑,当列表超过某个阈值时,我会警告我。

下面是正则表达式的一个示例:34.25.14.(227|228|229|230|243|244|245|246)

假设这些 IP 与 ACME 相关联。在后台,当用户选择 ACME(在我们的 UI 中)时,我正在填写一个包含所有这些可能数字的筛选器对象,并将它们作为 OR 查询提交到高度专业化的 Vertica 数据库。

我只是无法确定从所述正则表达式创建数字列表的优雅方法。

另一个方面是,产品另一部分中的java代码正在使用这些正则表达式来显示ACME,方法是使用java Pattern.compile(),这意味着客户“可以”创建一个复杂的正则表达式。到目前为止,我只见过它们使用上面所示的简单方法。

有没有一种方法可以基于正则表达式生成列表?

感谢您抽出宝贵时间接受采访。


答案 1

相关:

生成与正则表达式匹配的数据的库(有限制):http://code.google.com/p/xeger/

几种解决方案,例如将正则表达式转换为语法:使用正则表达式生成字符串而不是匹配它们


编辑:实际上,你可以让它工作!!!唯一需要解决的问题是施加一些特定于领域的约束,以防止像a +这样的组合爆炸。

如果向 Xeger 类添加如下内容:

public void enumerate() {
    System.out.println("enumerate: \"" + regex + "\"");
    int level = 0;
    String accumulated = "";
    enumerate(level, accumulated, automaton.getInitialState());
}

private void enumerate(int level, String accumulated, State state) {
    List<Transition> transitions = state.getSortedTransitions(true);
    if (state.isAccept()) {
        System.out.println(accumulated);
        return;
    }
    if (transitions.size() == 0) {
        assert state.isAccept();
        return;
    }
    int nroptions = state.isAccept() ? transitions.size() : transitions.size() - 1;
    for (int option = 0; option <= nroptions; option++) {
        // Moving on to next transition
        Transition transition = transitions.get(option - (state.isAccept() ? 1 : 0));
        for (char choice = transition.getMin(); choice <= transition.getMax(); choice++) {
            enumerate(level + 1, accumulated + choice, transition.getDest());
        }
    }
}

...以及像XegerTest这样的东西:

@Test
public void enumerateAllVariants() {
    //String regex = "[ab]{4,6}c";
    String regex = "34\\.25\\.14\\.(227|228|229|230|243|244|245|246)";
    Xeger generator = new Xeger(regex);
    generator.enumerate();
}

...你会得到这个:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running nl.flotsam.xeger.XegerTest
enumerate: "34\.25\.14\.(227|228|229|230|243|244|245|246)"
34.25.14.227
34.25.14.228
34.25.14.229
34.25.14.243
34.25.14.244
34.25.14.245
34.25.14.246
34.25.14.230
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.114 sec

...而且,你猜怎么着。对于“[ab]{4,6}c”,它正确地产生了112个变体。

这确实是一个快速而肮脏的实验,但它似乎;)工作。


答案 2

我会说技术上的答案是否定的,因为您可以在正则表达式中指定字符(数字)出现零次或多次。该“或更多”可以表示任意数量的数字。在实践中,您可以限制字符串的长度,并根据在正则表达式中找到的字符递归地构建字符串的超集,然后对它们进行文本处理以创建子集列表。