Verwenden von Regex zum Generieren von Zeichenfolgen, anstatt sie abzugleichen

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

  •  09-06-2019
  •  | 
  •  

Frage

Ich schreibe ein Java-Dienstprogramm, das mir hilft, jede Menge Daten für Leistungstests zu generieren.Es wäre Wirklich Es ist cool, einen regulären Ausdruck für Strings angeben zu können, damit mein Generator Dinge ausspuckt, die dazu passen.Gibt es da draußen etwas bereits Gebackenes, mit dem ich das machen kann?Oder gibt es eine Bibliothek, die mich den größten Teil des Weges dorthin bringt?

Danke

War es hilfreich?

Lösung

Bearbeiten:

Wie in den Kommentaren erwähnt, gibt es bei Google Code eine Bibliothek, um dies zu erreichen:http://code.google.com/p/xeger

Siehe auch https://github.com/mifmif/Generex wie vorgeschlagen von Mifmif

Originale Nachricht:

Erstens glaube ich, dass dies bei einem ausreichend komplexen regulären Ausdruck unmöglich sein kann.Aber Sie sollten in der Lage sein, etwas für einfache reguläre Ausdrücke zusammenzustellen.

Wenn Sie sich den Quellcode der Klasse java.util.regex.Pattern ansehen, werden Sie feststellen, dass diese eine interne Darstellung von Node-Instanzen verwendet.Jede der verschiedenen Musterkomponenten verfügt über eine eigene Implementierung einer Node-Unterklasse.Diese Knoten sind in einem Baum organisiert.

Indem Sie einen Besucher erzeugen, der diesen Baum durchläuft, sollten Sie in der Lage sein, eine überladene Generatormethode oder eine Art Builder aufzurufen, der etwas zusammenfügt.

Andere Tipps

Xeger (Java) ist dazu auch in der Lage:

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

Es ist zu spät, dem Originalplakat zu helfen, aber einem Neuling könnte es helfen. Generisch ist eine nützliche Java-Bibliothek, die viele Funktionen für die Verwendung regulärer Ausdrücke zum Generieren von Zeichenfolgen bietet (zufällige Generierung, Generierung einer Zeichenfolge basierend auf ihrem Index, Generierung aller Zeichenfolgen ...).

Beispiel :

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

Ich bin der Wurzel des Rollens gefolgt eigen Bibliothek dafür (in c#, sollte aber für einen Java-Entwickler leicht zu verstehen sein).

Rxrdg begann als Lösung für das Problem der Erstellung von Testdaten für ein reales Projekt.Die Grundidee besteht darin, die vorhandenen Validierungsmuster (reguläre Ausdrücke) zu nutzen, um Zufallsdaten zu erstellen, die diesen Mustern entsprechen.Auf diese Weise werden gültige Zufallsdaten erstellt.

Es ist nicht so schwierig, einen Parser für einfache Regex-Muster zu schreiben.Die Verwendung eines abstrakten Syntaxbaums zum Generieren von Zeichenfolgen dürfte noch einfacher sein.

Im Stackoverflow-Podcast 11:

Spolsky:Ja.Es gibt auch ein neues Produkt. Wenn Sie das Team System dort nicht verwenden möchten, haben unsere Freunde bei Redgate ein Produkt namens SQL Data Generator [http://www.red-gate.com/products/sql_data_generator/index.htm].Es kostet 295 US-Dollar und generiert lediglich einige realistische Testdaten.Und es macht Dinge wie die tatsächliche Generierung realer Städte in der Städtespalte, die tatsächlich existieren, und wenn es diese dann generiert, wird der Staat richtig gemacht, anstatt den Staat falsch zu machen, oder Staaten werden in deutsche Städte eingefügt und so ...Sie wissen, es generiert ziemlich realistisch aussehende Daten.Ich bin mir nicht wirklich sicher, was alle Funktionen sind.

Dies ist wahrscheinlich nicht das, wonach Sie suchen, aber es könnte ein guter Ausgangspunkt sein, anstatt einen eigenen zu erstellen.

Ich kann anscheinend nichts in Google finden, daher würde ich vorschlagen, das Problem anzugehen, indem man einen bestimmten regulären Ausdruck in die kleinsten Arbeitseinheiten zerlegt (\w, [x-x], \d usw.) und einige grundlegende Methoden zur Unterstützung schreibt diese regulären Ausdrucksphrasen.

Für \w hätten Sie also eine Methode getRandomLetter(), die einen beliebigen zufälligen Buchstaben zurückgibt, und Sie hätten auch getRandomLetter(char startLetter, char endLetter), die Ihnen einen zufälligen Buchstaben zwischen den beiden Werten liefert.

Ich weiß, dass es bereits eine akzeptierte Antwort gibt, aber ich habe sie verwendet Der Datengenerator von RedGate (das in Craigs Antwort erwähnte) und es funktioniert WIRKLICH gut für alles, was ich versucht habe.Es geht schnell und das weckt in mir den Wunsch, denselben regulären Ausdruck zu verwenden, um die echten Daten für Dinge wie Registrierungscodes zu generieren, die dieses Ding ausspuckt.

Es braucht einen regulären Ausdruck wie:

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

und es generiert jede Menge einzigartige Codes wie:

LLK-32U

Ist das ein großer geheimer Algorithmus, den RedGate herausgefunden hat und wir alle Pech haben, oder ist es etwas, was wir Normalsterblichen tatsächlich tun könnten?

Ich bin im Flug und habe gerade die Frage gesehen:Ich habe die einfachste, aber ineffiziente und unvollständige Lösung geschrieben.Ich hoffe, es kann Ihnen helfen, mit dem Schreiben Ihres eigenen Parsers zu beginnen:

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

Sie müssen Ihren eigenen Parser schreiben, wie es der Autor von String::Random (Perl) getan hat.Tatsächlich verwendet er in diesem Modul nirgendwo reguläre Ausdrücke, es ist einfach das, was Perl-Programmierer gewohnt sind.

Auf der anderen Seite können Sie vielleicht einen Blick darauf werfen die Quelle, um ein paar Hinweise zu bekommen.


BEARBEITEN:Verdammt, Blair war 15 Sekunden schneller als ich.

Es ist weit davon entfernt, einen vollständigen PCRE-Regexp zu unterstützen, aber ich habe die folgende Ruby-Methode geschrieben, um eine Regexp-ähnliche Zeichenfolge zu nehmen und eine Variation davon zu erstellen.(Für sprachbasiertes 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

Diese Frage ist sehr alt, aber ich bin bei meiner eigenen Suche darauf gestoßen, daher werde ich ein paar Links für andere hinzufügen, die möglicherweise nach der gleichen Funktionalität in anderen Sprachen suchen.

Wenn Sie „kritische“ Zeichenfolgen generieren möchten, sollten Sie Folgendes in Betracht ziehen:

Reiher http://elarson.pythonanywhere.com/das generiert „böse“ Strings, die Ihre regulären Ausdrücke abdecken

MUTREX http://cs.unibg.it/mutrex/das fehlererkennende Zeichenfolgen durch Regex-Mutation generiert

Beide sind akademische Werkzeuge (ich bin einer der Autoren des letzteren) und funktionieren einigermaßen gut.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top