在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
- 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