使用正则expression式来生成string,而不是匹配它们
我正在写一个Java实用程序,它可以帮助我生成性能testing的大量数据。 能够为string指定一个正则expression式真的很酷,这样我的生成器就会吐出与之相匹配的东西。 有没有已经出炉的东西,我可以用它来做到这一点? 还是有一个图书馆,让我在那里的大部分路?
谢谢
编辑:
正如评论中提到的那样,谷歌代码中有一个库可以实现这个function: http : //code.google.com/p/xeger
参见Mifmifbuild议的https://github.com/mifmif/Generex
原始信息:
首先,用足够复杂的正则expression式,我相信这是不可能的。 但是你应该能够把简单的正则expression式放在一起。
如果你看一下java.util.regex.Pattern类的源代码,你会发现它使用Node实例的内部表示。 每个不同的模式组件都有自己的Node子类的实现。 这些节点被组织成一棵树。
通过生成一个遍历这棵树的访问者,你应该能够调用一个重载的生成器方法或者某种将一些东西拼凑在一起的生成器。
Xeger(Java)也可以这样做:
String regex = "[ab]{4,6}c"; Xeger generator = new Xeger(regex); String result = generator.generate(); assert result.matches(regex);
帮助原来的海报已经太晚了,但可以帮助新人。 Generex是一个有用的Java库,它提供了许多使用正则expression式来生成string的function(随机生成,根据索引生成string,生成所有string…)。
例如:
Generex generex = new Generex("[0-3]([ac]|[eg]{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
Visual Studio Team System确实包含了这样的内容。 一探究竟
虽然没有太多的帮助,但很抱歉。
我已经走了自己的库的根源(在C#中,但应该是一个Java开发人员容易理解)。
Rxrdg开始作为一个解决scheme,为现实生活中的项目创buildtesting数据的问题。 基本思路是利用现有的(正则expression式)validation模式来创build符合这种模式的随机数据。 这样就创build了有效的随机数据。
为简单的正则expression式模式编写parsing器并不难。 使用抽象语法树生成string应该更容易。
在stackoverflow播客11:
Spolsky:是的。 还有一种新产品,如果你不想使用团队系统,那么我们在Redgate的朋友有一个叫做SQL Data Generator的产品[ http://www.red-gate.com/products/sql_data_generator/index.htm%5D 。 这是$ 295,它只是产生一些现实的testing数据。 它实际上生成真正存在的城市列中的真实城市,然后当它产生这些城市时,它将获得正确的状态,而不是使状态错误,或者将状态放入德国的城市以及像…你知道,它会产生相当逼真的数据。 我不确定所有的function。
这可能不是你正在寻找的,但它可能是一个很好的开始,而不是创build自己的。
我似乎无法在谷歌find任何东西,所以我会build议通过parsing给定的正则expression式到最小的工作单位(\ w,[xx],\ d等),并编写一些基本的方法来支持解决问题那些正则expression式短语。
所以对于\ w你将有一个方法getRandomLetter()返回任意的随机字母,你也有getRandomLetter(char startLetter,char endLetter),它给你一个随机的两个值之间的字母。
我知道已经有了一个可以接受的答案,但是我一直在使用RedGate的数据生成器 (在Craig的答案中提到的那个),它对我所投入的所有东西都非常有效。 这很快,这让我想要使用相同的正则expression式来生成真正的数据,如注册码,这个东西吐出来的东西。
它需要一个正则expression式:
[A-Z0-9]{3,3}-[A-Z0-9]{3,3}
它会产生大量的独特的代码,如:
LLK-32U
这是RedGate算出来的一个很大的秘密algorithm,我们都运气不好,或者只是一些凡人实际上可以做的事情?
你将不得不编写自己的parsing器,就像String :: Random(Perl)的作者一样。 事实上,他不会在该模块的任何地方使用正则expression式,这正是perl编码器所习惯的。
另一方面,也许你可以看看源头 ,得到一些指针。
编辑:该死的,布莱尔打了我15秒的冲。
它远不支持完整的PCRE正则expression式,但是我写了下面的Ruby方法来获取类似正则expression式的string并在其上生成变体。 (对于基于语言的CAPTCHA。)
# 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
我在飞机上,只是看到了这个问题:我写了最简单,但效率低下和不完整的解决scheme。 我希望它可以帮助你开始编写你自己的parsing器:
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); }
添加另一个工具,我没有看到在这里列出,这对我工作。 (我尝试了来自Goran – Rxrdg的C#解决scheme – 但与我的解决scheme不build立)。
下面的链接是非常简单,容易,做了我的工作: http : //uttool.com/text/regexstr/default.aspx
如果你想产生“关键”的string,你可能要考虑:
生成覆盖正则expression式的“邪恶”string的EGRET http://elarson.pythonanywhere.com/
MUTREX http://cs.unibg.it/mutrex/通过正则expression式突变产生错误检测string
两者都是学术工具(我是后者的作者之一),工作得相当好。
这个问题非常古老,但是我在自己的search中偶然发现了这个问题,所以我将包含一些其他可能在其他语言中search相同function的链接。
- 这里有一个Node.js库: https : //github.com/fent/randexp.js
- 这里有一个PHP库: https : //github.com/icomefromthenet/ReverseRegex
- PHP faker包中包含一个“regexify”方法来完成这个工作: https ://packagist.org/packages/fzaninotto/faker