パフォーマンス テスト用の大量のデータを生成するのに役立つ Java ユーティリティを作成しています。私のジェネレーターがこれに一致するものを吐き出すように、文字列の正規表現を指定できると本当にクールです。これを行うために使用できる、すでに焼き上げられたものはありますか?または、そこにほとんどの方法でアクセスできるライブラリはありますか?
ありがとう
編集:
この質問に関する推奨ライブラリの完全なリスト:
* - によって異なりますdk.brics.automaton
編集: コメントで述べたように、これを実現するために Google Code で利用できるライブラリがあります: https://code.google.com/archive/p/xeger/
Mifmifが提案するhttps://github.com/mifmif/Generexも参照してください。
オリジナルメッセージ:
まず、十分に複雑な正規表現では、これは不可能だと思います。しかし、単純な正規表現のために何かをまとめることができるはずです。
クラス java.util.regex.Pattern のソース コードを見ると、Node インスタンスの内部表現を使用していることがわかります。さまざまなパターン コンポーネントのそれぞれに、Node サブクラスの独自の実装があります。これらのノードはツリーに編成されています。
このツリーをトラバースするビジターを生成することにより、オーバーロードされたジェネレーター メソッドまたは何かをまとめるビルダーのようなものを呼び出すことができるはずです。
元の投稿者を助けるには遅すぎますが、初心者を助けることができます. 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);
私はそのために独自のライブラリを展開するルートに行きました(C#ではありますが、Java開発者にとっては理解しやすいはずです)。
Rxrdg は、実際のプロジェクトのテスト データを作成する際の問題の解決策として始まりました。基本的な考え方は、既存の (正規表現) 検証パターンを活用して、そのようなパターンに準拠するランダム データを作成することです。このようにして、有効なランダム データが作成されます。
単純な正規表現パターンのパーサーを作成することはそれほど難しくありません。抽象構文ツリーを使用して文字列を生成すると、さらに簡単になります。
stackoverflowポッドキャスト11:
スポルスキー:うん。新製品もあります。チームシステムを使用したくない場合は、Redgateの友人がSQL DataGenerator[ http://www.red-gate.com/products/sql_data_generator/index.htm]という製品を持っています。 。295ドルで、現実的なテストデータを生成するだけです。そして、実際に存在する都市列に実際の都市を生成し、それらを生成すると、状態を間違えたり、ドイツの都市に州を配置したりするのではなく、正しい状態になります...ご存知のように、それはかなりリアルな外観のデータを生成します。すべての機能が何であるかはよくわかりません。
これはおそらくあなたが探しているものではありませんが、独自に作成するのではなく、出発点として適している可能性があります。
グーグルで何も見つからないようですので、与えられた正規表現を最小の作業単位(\ w、[xx]、\ dなど)に解析し、サポートするいくつかの基本的なメソッドを作成することで、問題に取り組むことをお勧めしますそれらの正規表現フレーズ。
したがって、\ wの場合、任意のランダムな文字を返すgetRandomLetter()メソッドがあり、2つの値の間にランダムな文字を返すgetRandomLetter(char startLetter、char endLetter)もあります。
私は飛行中で、質問を見ました:私は最も簡単ですが非効率的で不完全な解決策を書きました。独自のパーサーの作成を開始するのに役立つことを願っています。
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);
}
すでに受け入れられている答えがあることは知っていますが、私はRedGateのデータジェネレーター(Craigの答えで言及されているもの)を使用しており、それは私が投げたすべてのものに対して本当にうまく機能します。迅速で、同じ正規表現を使用して、このものが吐き出す登録コードなどの実際のデータを生成したいと思うようになります。
次のような正規表現が必要です。
[A-Z0-9]{3,3}-[A-Z0-9]{3,3}
そしてそれは次のようなたくさんのユニークなコードを生成します:
LLK-32U
これは、RedGateが理解した大きな秘密のアルゴリズムであり、私たち全員が運が悪かったのでしょうか、それとも単なる人間が実際に実行できることでしょうか。
String::Random (Perl) の作成者が行ったように、独自のパーサーを作成する必要があります。実際、彼はそのモジュールのどこにも正規表現を使用していません。これは、perl コーダーが慣れているものです。
一方、sourceを見て、いくつかのポインターを取得できるかもしれません。
編集:くそー、ブレアは私を15秒打ち負かしました。
完全なPCREregexpをサポートすることにはほど遠いですが、regexpのような文字列を取得してそのバリエーションを生成するために、次のRubyメソッドを作成しました。(言語ベースの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