没错,你没有看错。我需要一个能够从正则表达式中 生成 随机文本的工具。因此,这个文本应该是随机的,但要与正则表达式匹配。目前似乎不存在这样的工具,但我可能是错的。
这里有一个例子:如果输入'[ab]*c
',那么这个工具就可以生成以下样本:
abc
abbbc
bac
等等。
更新:我自己创建了一个工具:Xeger。请查看http://code.google.com/p/xeger/。
没错,你没有看错。我需要一个能够从正则表达式中 生成 随机文本的工具。因此,这个文本应该是随机的,但要与正则表达式匹配。目前似乎不存在这样的工具,但我可能是错的。
这里有一个例子:如果输入'[ab]*c
',那么这个工具就可以生成以下样本:
abc
abbbc
bac
等等。
更新:我自己创建了一个工具:Xeger。请查看http://code.google.com/p/xeger/。
我刚刚创建了一个库,可以用来做这件事。它托管在这里:http://code.google.com/p/xeger/。使用前请仔细阅读说明(特别是下载另一个必需的库的部分)。;-)
以下是使用方法:
String regex = "[ab]{4,6}c";
Xeger generator = new Xeger(regex);
String result = generator.generate();
assert result.matches(regex);
我不知道有这样的库。如果你想自己编写一个,那么以下可能是你需要采取的步骤:
结果是一个由原始正则表达式接受的单词。更多信息请参见例如将正则表达式转换为确定性有限自动机。
基于Wilfred Springer的解决方案和http://www.brics.dk/~amoeller/automaton/,我构建了另一个生成器。
它不使用递归。它以模式/正则表达式最小字符串长度和最大字符串长度作为输入。结果是在最小和最大长度之间的接受字符串。它还允许一些XML“简写字符类”。我用它来生成有效的字符串以便于XML样本生成器构建限制条件。
public static final String generate(final String pattern, final int minLength, final int maxLength) {
final String regex = pattern
.replace("\\d", "[0-9]") // Used d=Digit
.replace("\\w", "[A-Za-z0-9_]") // Used d=Word
.replace("\\s", "[ \t\r\n]"); // Used s="White"Space
final Automaton automaton = new RegExp(regex).toAutomaton();
final Random random = new Random(System.nanoTime());
final List<String> validLength = new LinkedList<>();
int len = 0;
final StringBuilder builder = new StringBuilder();
State state = automaton.getInitialState();
Transition[] transitions;
while(len <= maxLength && (transitions = state.getSortedTransitionArray(true)).length != 0) {
final int option = random.nextInt(transitions.length);
if (state.isAccept() && len >= minLength && len <= maxLength) validLength.add(builder.toString());
final Transition t = transitions[option]; // random transition
builder.append((char) (t.getMin()+random.nextInt(t.getMax()-t.getMin()+1))); len ++;
state = t.getDest();
}
if(validLength.size() == 0) throw new IllegalArgumentException(automaton.toString()+" , "+minLength+" , "+maxLength);
return validLength.get(random.nextInt(validLength.size()));
}