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

在Java中,如何从特定的正则表达式创建所有可能的数字的列表?,java,regex,Java,Regex,我有一个奇怪的问题,至少我从未遇到过。我有一个先决条件,客户可以使用与标签关联的简单正则表达式。标签是他们关心的全部。我想做的是创建一个所有可能的数字的列表,这些数字将匹配这些正则表达式中的每一个。当列表超出某个阈值时,我会有逻辑警告我 下面是正则表达式的示例:34.25.14.(227 | 228 | 229 | 230 | 243 | 244 | 245 | 246) 假设这些ip与ACME关联。在幕后,当用户选择ACME(在我们的UI中)时,我填写一个包含所有这些可能数字的筛选器对象,并将

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

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

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

我只是不能确定一种优雅的方法,从上述正则表达式创建一个数字列表

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

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

谢谢您的时间。

相关:

生成与正则表达式匹配的数据的库(有限制):

有几种解决方案,例如将正则表达式转换为语法:


编辑:实际上,你可以让它工作唯一需要解决的问题是施加一些特定于领域的约束,以防止像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());
        }
    }
}
。。。您将获得以下信息:

-------------------------------------------------------
 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个变体


这确实是一个又快又脏的实验,但似乎有效

我认为技术上的答案是否定的,因为您可以在正则表达式中指定一个字符(数字)出现零次或多次。“或更多”可以表示任意大的位数。实际上,您可能可以限制字符串的长度,并根据在正则表达式中找到的字符递归地构建字符串的超集,然后将它们文本化以创建子集列表。

注释:正则表达式是一种递归枚举语言,因此,存在一种可以枚举所有有效字符串的算法

即使对于像Java这样更复杂的语言,也可以有一个枚举所有Java程序的算法;无论您的特定Java程序是如何编写的,该算法都会在有限时间内输出与您的完全匹配的Java程序


但并不是所有的语言都是这样可枚举的;那就是我们知道存在的语言,但我们不能用它们说话。它们永远逃避任何像我们这样的原始智能,而这只是一台图灵机器。

蛮力、多线程、CPU负载100%:

import java.util.regex.Pattern;

public class AllIP
{
   public static void main( String[] args )
   {
      final Pattern p = Pattern.compile( "34.25.14.(227|228|229|230|243|244|245|246)" );

      int step = 256 / Runtime.getRuntime().availableProcessors();
      for( int range = 0; range < 256; range += step )
      {
         final int from = range;
         final int to   = range + step;
         new Thread(){
            public @Override void run(){
               long atStart = System.currentTimeMillis();
               for( int i = from; i < to ; ++i )
                  for( int j = 1; j < 255; ++j )
                     for( int k = 1; k < 255; ++k )
                        for( int l = 1; l < 255; ++l )
                        {
                           String ip = String.format( "%d.%d.%d.%d", i,j,k,l );
                           if( p.matcher( ip ).matches())
                           {
                              System.out.println( ip );
                           }
                        }
               System.out.println( System.currentTimeMillis() - atStart );
            }
         }.start();
      }
   }
}
import java.util.regex.Pattern;
公共类AllIP
{
公共静态void main(字符串[]args)
{
最终模式p=Pattern.compile(“34.25.14.(227 | 228 | 229 | 230 | 243 | 244 | 245 | 246)”;
int step=256/Runtime.getRuntime().availableProcessors();
用于(整数范围=0;范围<256;范围+=步长)
{
最终int from=范围;
最终int to=范围+步长;
新线程(){
public@Override void run(){
long atStart=System.currentTimeMillis();
for(int i=从;i<到;++i)
对于(int j=1;j<255;++j)
对于(int k=1;k<255;++k)
对于(int l=1;l<255;++l)
{
字符串ip=String.format(“%d.%d.%d.%d”,i,j,k,l);
if(p.matcher(ip.matches())
{
系统输出打印项次(ip);
}
}
System.out.println(System.currentTimeMillis()-atStart);
}
}.start();
}
}
}
只是为了好玩

  • 34.25.14.227
  • 34.25.14.228
  • 34.25.14.229
  • 34.25.14.230
  • 34.25.14.243
  • 34.25.14.244
  • 34.25.14.245
  • 34.25.14.246
运行时间:01:18:59

操作系统

  • Microsoft Windows XP Professionnel 32位SP3
中央处理器

  • 英特尔至强W3565@3.20GHz 39°C

  • 布隆菲尔德45nm技术

公羊

  • 532MHz(7-7-7-20)下4,00 Go双通道DDR3
主板

  • 联想(1366针LGA)

    • 这个问题太令人惊讶了

      我用一个简单的JavaCC语法和3个类解决了这个问题:常量、变量和Main。 我用作输入的表达式是
      (34 | 45).2\d.14.(227 | 228 | 229 | 230 | 243 | 244 | 245 | 246)
      ,请注意\d以指定可变部分

      以下是JavaCC语法:

      options
      {
          static         = false;
          FORCE_LA_CHECK = true;
          LOOKAHEAD      = 5;
      }
      
      PARSER_BEGIN( IPGeneratorFromRegExp )
      package hpms.study.jj;
      
      public class IPGeneratorFromRegExp
      {
          public final java.util.SortedSet< hpms.study.IPPart > _a = new java.util.TreeSet< hpms.study.IPPart >();
          public final java.util.SortedSet< hpms.study.IPPart > _b = new java.util.TreeSet< hpms.study.IPPart >();
          public final java.util.SortedSet< hpms.study.IPPart > _c = new java.util.TreeSet< hpms.study.IPPart >();
          public final java.util.SortedSet< hpms.study.IPPart > _d = new java.util.TreeSet< hpms.study.IPPart >();
      
      }// class IPGeneratorFromRegExp
      
      PARSER_END( IPGeneratorFromRegExp )
      
      SKIP :
      {
        " "
      | "\r"
      | "\t"
      | "\n"
      }
      
      TOKEN :
      {
          < IPPARTX   :                          (["1"-"9"] | "\\d" ) > 
      |   < IPPARTXX  :     (["1"-"9"] | "\\d" ) (["0"-"9"] | "\\d" ) > 
      |   < IPPART1XX : "1" (["0"-"9"] | "\\d" ) (["0"-"9"] | "\\d" ) >
      |   < IPPART2XX : "2" (["0"-"4"] | "\\d" ) (["0"-"9"] | "\\d" ) >
      |   < IPPART25X : "2" "5"                  (["0"-"5"] | "\\d" ) >
      }
      
      void part( java.util.SortedSet< hpms.study.IPPart > parts ):{ Token token = null; }
      {
          (
              token=<IPPART25X>
          |   token=<IPPART2XX>
          |   token=<IPPART1XX>
          |   token=<IPPARTXX>
          |   token=<IPPARTX>
          ){
              parts.add(
                  token.image.contains( "\\d" )
                      ? new hpms.study.Variable( token.image )
                      : new hpms.study.Constant( token.image ));
          }
      }
      
      void expr( java.util.SortedSet< hpms.study.IPPart > parts ):{}
      {
          "(" part( parts ) ( "|" part( parts ))+ ")"
      }
      
      void analyze() :{}
      {
          ( part( _a ) | expr( _a )) "."
          ( part( _b ) | expr( _b )) "."
          ( part( _c ) | expr( _c )) "."
          ( part( _d ) | expr( _d ))
      }
      
      选项
      {
      静态=假;
      强制检查=真;
      前瞻=5;
      }
      解析器_BEGIN(IPGeneratorFromRegExp)
      包hpms.study.jj;
      公共类IPGeneratorFromRegExp
      {
      公共最终java.util.SortedSet\u a=new java.util.TreeSet();
      公共最终java.util.SortedSet\u b=new java.util.TreeSet();
      公共最终java.util.SortedSet\u c=new java.util.TreeSet();
      public final java.util.SortedSet\u d=new java.util.TreeSet();
      }//类IPGeneratorFromRegExp
      解析器_END(IPGeneratorFromRegExp)
      跳过:
      {
      " "
      |“\r”
      |“\t”
      |“\n”
      }
      代币:
      {
      
      |options
      {
          static         = false;
          FORCE_LA_CHECK = true;
          LOOKAHEAD      = 5;
      }
      
      PARSER_BEGIN( IPGeneratorFromRegExp )
      package hpms.study.jj;
      
      public class IPGeneratorFromRegExp
      {
          public final java.util.SortedSet< hpms.study.IPPart > _a = new java.util.TreeSet< hpms.study.IPPart >();
          public final java.util.SortedSet< hpms.study.IPPart > _b = new java.util.TreeSet< hpms.study.IPPart >();
          public final java.util.SortedSet< hpms.study.IPPart > _c = new java.util.TreeSet< hpms.study.IPPart >();
          public final java.util.SortedSet< hpms.study.IPPart > _d = new java.util.TreeSet< hpms.study.IPPart >();
      
      }// class IPGeneratorFromRegExp
      
      PARSER_END( IPGeneratorFromRegExp )
      
      SKIP :
      {
        " "
      | "\r"
      | "\t"
      | "\n"
      }
      
      TOKEN :
      {
          < IPPARTX   :                          (["1"-"9"] | "\\d" ) > 
      |   < IPPARTXX  :     (["1"-"9"] | "\\d" ) (["0"-"9"] | "\\d" ) > 
      |   < IPPART1XX : "1" (["0"-"9"] | "\\d" ) (["0"-"9"] | "\\d" ) >
      |   < IPPART2XX : "2" (["0"-"4"] | "\\d" ) (["0"-"9"] | "\\d" ) >
      |   < IPPART25X : "2" "5"                  (["0"-"5"] | "\\d" ) >
      }
      
      void part( java.util.SortedSet< hpms.study.IPPart > parts ):{ Token token = null; }
      {
          (
              token=<IPPART25X>
          |   token=<IPPART2XX>
          |   token=<IPPART1XX>
          |   token=<IPPARTXX>
          |   token=<IPPARTX>
          ){
              parts.add(
                  token.image.contains( "\\d" )
                      ? new hpms.study.Variable( token.image )
                      : new hpms.study.Constant( token.image ));
          }
      }
      
      void expr( java.util.SortedSet< hpms.study.IPPart > parts ):{}
      {
          "(" part( parts ) ( "|" part( parts ))+ ")"
      }
      
      void analyze() :{}
      {
          ( part( _a ) | expr( _a )) "."
          ( part( _b ) | expr( _b )) "."
          ( part( _c ) | expr( _c )) "."
          ( part( _d ) | expr( _d ))
      }
      
           Reader                source      = new StringReader( _regExp.getText());
           IPGeneratorFromRegExp ipGenerator = new IPGeneratorFromRegExp( source );
           ipGenerator.analyze();
      
           SortedSet< String > a = new TreeSet<>();
           SortedSet< String > b = new TreeSet<>();
           SortedSet< String > c = new TreeSet<>();
           SortedSet< String > d = new TreeSet<>();
           for( IPPart<?> part : ipGenerator._a ) part.expandTo( a );
           for( IPPart<?> part : ipGenerator._b ) part.expandTo( b );
           for( IPPart<?> part : ipGenerator._c ) part.expandTo( c );
           for( IPPart<?> part : ipGenerator._d ) part.expandTo( d );
      
           _result.clear();
           for( String ac : a )
           {
              for( String bc : b )
              {
                 for( String cc : c )
                 {
                    for( String dc : d )
                    {
                       _result.add( ac + '.' + bc + '.' + cc + '.'  + dc );
                    }// for
                 }// for
              }// for
           }// for