我正在编写一个Java工具,以帮助我生成大量数据进行性能测试。如果能够为字符串指定正则表达式,让我的生成器输出匹配该正则表达式的内容,那将是非常酷的。
是否已经有这样的现成工具可以使用?或者是否有类库可以帮我实现这个功能?
首先,用足够复杂的正则表达式来说,我认为这是不可能的。但是您应该能够为简单的正则表达式编写一些代码。
如果您查看 java.util.regex.Pattern 类的源代码,您将看到它使用 Node 实例的内部表示法。每个不同的模式组件都有它们自己的 Node 子类实现。这些节点被组织成一棵树。
通过创建一个遍历此树的访问者,您应该能够调用重载生成器方法或某种构建器,然后拼凑出一些东西。
dk.brics.automaton
,因此请准备添加第三方 pom 依赖项。大多数人不介意,但我希望有更紧凑的东西。 - Sridhar Sarnobat虽然已经来不及帮助原始帖子的发布者,但它可能有助于新手。 Generex 是一个有用的 Java 库,为使用正则表达式生成字符串(随机生成、基于索引生成字符串、生成所有字符串等)提供了许多功能。
示例:
Generex generex = new Generex("[0-3]([a-c]|[e-g]{1,2})");
// generate the second String in lexicographical order that matches the given Regex.
String secondString = generex.getMatchedString(2);
System.out.println(secondString);// it print '0b'
// Generate all String that matches the given Regex.
List<String> matchedStrs = generex.getAllMatchedStrings();
// Using Generex iterator
Iterator iterator = generex.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
// it prints 0a 0b 0c 0e 0ee 0e 0e 0f 0fe 0f 0f 0g 0ge 0g 0g 1a 1b 1c 1e
// 1ee 1e 1e 1f 1fe 1f 1f 1g 1ge 1g 1g 2a 2b 2c 2e 2ee 2e 2e 2f 2fe 2f 2f 2g
// 2ge 2g 2g 3a 3b 3c 3e 3ee 3e 3e 3f 3fe 3f 3f 3g 3ge 3g 3g 1ee
// Generate random String
String randomStr = generex.random();
System.out.println(randomStr);// a random value from the previous String list
披露
本帖所提到的项目归回答问题的用户(Mifmif)所有。根据规定,需要进行披露。
Xeger(Java)也能够实现此功能:
String regex = "[ab]{4,6}c";
Xeger generator = new Xeger(regex);
String result = generator.generate();
assert result.matches(regex);
这个问题很古老,但对我来说仍然是实际问题。我尝试了xeger和Generex,但它们似乎都不能满足我的要求。它们实际上无法处理一些正则表达式模式(例如a{60000}
),对于其他一些模式(例如(A|B|C|D|E|F)
),它们只能产生部分可能的值。由于我没有找到任何其他合适的解决方案 - 我创建了自己的库。
https://github.com/curious-odd-man/RgxGen
该库可用于生成匹配和不匹配的字符串。
maven central也有相关的构件。
使用示例:
RgxGen rgxGen = new RgxGen(aRegex); // Create generator
String s = rgxGen.generate(); // Generate new random value
我正在飞行中,刚看到这个问题:我已经写了一个最简单但低效和不完整的解决方案。我希望它能帮助你开始编写自己的解析器:
public static void main(String[] args) {
String line = "[A-Z0-9]{16}";
String[] tokens = line.split(line);
char[] pattern = new char[100];
int i = 0;
int len = tokens.length;
String sep1 = "[{";
StringTokenizer st = new StringTokenizer(line, sep1);
while (st.hasMoreTokens()) {
String token = st.nextToken();
System.out.println(token);
if (token.contains("]")) {
char[] endStr = null;
if (!token.endsWith("]")) {
String[] subTokens = token.split("]");
token = subTokens[0];
if (!subTokens[1].equalsIgnoreCase("*")) {
endStr = subTokens[1].toCharArray();
}
}
if (token.startsWith("^")) {
String subStr = token.substring(1, token.length() - 1);
char[] subChar = subStr.toCharArray();
Set set = new HashSet<Character>();
for (int p = 0; p < subChar.length; p++) {
set.add(subChar[p]);
}
int asci = 1;
while (true) {
char newChar = (char) (subChar[0] + (asci++));
if (!set.contains(newChar)) {
pattern[i++] = newChar;
break;
}
}
if (endStr != null) {
for (int r = 0; r < endStr.length; r++) {
pattern[i++] = endStr[r];
}
}
} else {
pattern[i++] = token.charAt(0);
}
} else if (token.contains("}")) {
char[] endStr = null;
if (!token.endsWith("}")) {
String[] subTokens = token.split("}");
token = subTokens[0];
if (!subTokens[1].equalsIgnoreCase("*")) {
endStr = subTokens[1].toCharArray();
}
}
int length = Integer.parseInt((new StringTokenizer(token, (",}"))).nextToken());
char element = pattern[i - 1];
for (int j = 0; j < length - 1; j++) {
pattern[i++] = element;
}
if (endStr != null) {
for (int r = 0; r < endStr.length; r++) {
pattern[i++] = endStr[r];
}
}
} else {
char[] temp = token.toCharArray();
for (int q = 0; q < temp.length; q++) {
pattern[i++] = temp[q];
}
}
}
String result = "";
for (int j = 0; j < i; j++) {
result += pattern[j];
}
System.out.print(result);
}
在stackoverflow播客11中:
Spolsky:是的。还有一个新产品,如果您不想使用Team System,我们的朋友Redgate有一个名为SQL Data Generator的产品[http://www.red-gate.com/products/sql_data_generator/index.htm]。它售价295美元,可以生成一些逼真的测试数据。它会在城市列中生成实际存在的城市,并在生成这些城市时正确获取州名,而不是将州名放入德国城市等等。你知道的,它生成的数据看起来相当逼真。我不太确定所有的功能都是什么。
这可能不是您要找的,但它可能是一个好的起点,而不是创建自己的数据。
我似乎在谷歌上找不到任何东西,所以建议通过将给定的正则表达式解析为最小的工作单元(\w,[x-x],\d等)并编写一些支持这些正则表达式短语的基本方法来解决问题。
因此,对于\w,您将拥有一个方法getRandomLetter(),它返回任何随机字母,您还将拥有getRandomLetter(char startLetter,char endLetter),它为您提供两个值之间的随机字母。
我知道已经有一个被接受的答案,但是我一直在使用RedGate的数据生成器(在Craig的答案中提到的那个),它对我投入的所有东西都非常有效。它很快,这让我想使用相同的正则表达式来生成像注册码这样的真实数据。
它需要一个正则表达式,如下所示:
[A-Z0-9]{3,3}-[A-Z0-9]{3,3}
它会生成许多独特的代码,例如:
LLK-32U
这是一种RedGate发现的重要算法吗?还是我们这些凡人也可以做到的呢?
虽然它远未支持完整的PCRE正则表达式,但我编写了以下Ruby方法来接受类似正则表达式的字符串并生成其变体。(用于基于语言的验证码。)
# q = "(How (much|many)|What) is (the (value|result) of)? :num1 :op :num2?"
# values = { :num1=>42, :op=>"plus", :num2=>17 }
# 4.times{ puts q.variation( values ) }
# => What is 42 plus 17?
# => How many is the result of 42 plus 17?
# => What is the result of 42 plus 17?
# => How much is the value of 42 plus 17?
class String
def variation( values={} )
out = self.dup
while out.gsub!( /\(([^())?]+)\)(\?)?/ ){
( $2 && ( rand > 0.5 ) ) ? '' : $1.split( '|' ).random
}; end
out.gsub!( /:(#{values.keys.join('|')})\b/ ){ values[$1.intern] }
out.gsub!( /\s{2,}/, ' ' )
out
end
end
class Array
def random
self[ rand( self.length ) ]
end
end