正規表現を使用して文字列を照合するのではなく生成する

StackOverflow https://stackoverflow.com/questions/22115

  •  09-06-2019
  •  | 
  •  

質問

私はパフォーマンス テスト用の大量のデータを生成するのに役立つ Java ユーティリティを作成しています。だろう 本当に 文字列の正規表現を指定できるので、ジェネレーターがこれに一致するものを吐き出すことができるのは素晴らしいことです。これを行うために使用できる、すでに焼き上がったものはありますか?それとも、ほとんどの場合にそこに行くことができる図書館はありますか?

ありがとう

役に立ちましたか?

解決

編集:

コメントで述べたように、これを実現するために Google Code で利用できるライブラリがあります。http://code.google.com/p/xeger

こちらも参照 https://github.com/mifmif/Generex によって提案されたように ミフミフ

オリジナルメッセージ:

まず、十分に複雑な正規表現では、これは不可能である可能性があると思います。ただし、単純な正規表現を何かをまとめることができるはずです。

クラス java.util.regex.Pattern のソース コードを見ると、Node インスタンスの内部表現を使用していることがわかります。さまざまなパターン コンポーネントにはそれぞれ、Node サブクラスの独自の実装があります。これらのノードはツリーに編成されます。

このツリーをトラバースするビジターを生成することにより、オーバーロードされたジェネレーター メソッドや、何かをまとめるある種のビルダーを呼び出すことができるはずです。

他のヒント

ゼーガー (Java) もそれを行うことができます:

String regex = "[ab]{4,6}c";
Xeger generator = new Xeger(regex);
String result = generator.generate();
assert result.matches(regex);

元の投稿者を助けるには遅すぎますが、新規投稿者を助けることができるかもしれません。 ジェネレックス は、正規表現を使用して文字列を生成するための多くの機能 (ランダム生成、インデックスに基づいた文字列の生成、すべての文字列の生成など) を提供する便利な 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

私はローリングの根元に行ってしまった 自分の そのためのライブラリ (C# ですが、Java 開発者にとっては理解しやすいはずです)。

Rxrdg は、実際のプロジェクトのテスト データを作成する問題の解決策として始まりました。基本的な考え方は、既存の (正規表現) 検証パターンを利用して、そのようなパターンに準拠するランダム データを作成することです。このようにして、有効なランダム データが作成されます。

単純な正規表現パターンのパーサーを作成することはそれほど難しくありません。抽象構文ツリーを使用して文字列を生成するのはさらに簡単になります。

stackoverflow ポッドキャスト 11:

スポルスキー:はい。新しい製品もあります。Team System を使用したくない場合は、Redgate の友人が SQL Data Generator と呼ばれる製品を提供しています。http://www.red-gate.com/products/sql_data_generator/index.htm]. 。価格は 295 ドルで、現実的なテスト データを生成するだけです。そして、実際に存在する都市列に実際の都市を生成するようなことを行います。そして、それらを生成するときに、州を間違ったり、ドイツの都市に州を入れたりするのではなく、正しい州を取得します...ご存知のとおり、かなり現実的なデータが生成されます。すべての機能が何なのかよくわかりません。

これはおそらくあなたが探しているものではありませんが、独自のものを作成する代わりに、出発点としては良いかもしれません。

Googleで何も見つからないようなので、指定された正規表現を最小の作業単位(\w、[x-x]、\dなど)に解析し、サポートするための基本的なメソッドを作成することで問題に取り組むことをお勧めします。これらの正規表現フレーズ。

したがって、 \w の場合、ランダムな文字を返す getRandomLetter() メソッドがあり、また 2 つの値の間のランダムな文字を与える getRandomLetter(char startLetter, char endLetter) もあります。

すでに受け入れられた答えがあることは知っていますが、私はこれまで使用してきました RedGateのデータジェネレーター (Craigの答えで言及されているもの)そしてそれは私が投げたすべてのものに対して本当にうまく機能します。これは速いので、同じ正規表現を使用して、このものが吐き出す登録コードなどの実際のデータを生成したいと思います。

次のような正規表現を受け取ります。

[A-Z0-9]{3,3}-[A-Z0-9]{3,3}

そして、次のようなユニークなコードを大量に生成します。

LLK-32U

これは RedGate が見つけ出した大きな秘密のアルゴリズムで、私たち全員が運が悪いのでしょうか、それとも私たち凡夫でも実際にできることなのでしょうか?

私は飛行機に乗っていて、たった今質問を目にしました。私は最も簡単ですが非効率的で不完全な解決策を書きました。独自のパーサーを書き始めるのに役立つことを願っています。

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);
}

String::Random (Perl) の作者がやったように、独自のパーサーを作成する必要があります。実際、彼はそのモジュールのどこにも正規表現を使用していません。それは Perl コーダーが慣れているものにすぎません。

一方、おそらくあなたは見てみることができます 起源, 、いくつかのヒントを得るために。


編集:くそー、ブレアは私に15秒の差で負けた。

完全な PCRE 正規表現のサポートには程遠いですが、正規表現のような文字列を取得してそのバリエーションを生成する次の 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

この質問は非常に古いものですが、私自身の検索で偶然見つけたので、他の言語で同じ機能を検索している可能性のある他の人のために、いくつかのリンクを含めます。

「クリティカル」文字列を生成したい場合は、次のことを考慮するとよいでしょう。

サギ http://elarson.pythananywhere.com/正規表現をカバーする「悪意のある」文字列を生成します

ムトレックス http://cs.unibg.it/mutrex/正規表現の突然変異によって障害検出文字列を生成します

どちらも学術的なツールであり (私は後者の著者の 1 人です)、かなりうまく機能します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top