Domanda

Sto scrivendo un'utilità Java che mi aiuta a generare un sacco di dati per i test delle prestazioni.Sarebbe Veramente bello poter specificare una regex per Strings in modo che il mio generatore sputi cose che corrispondono a questo.C'è qualcosa là fuori già cotto che posso usare per fare questo?Oppure c'è una biblioteca che mi porta quasi fin lì?

Grazie

È stato utile?

Soluzione

Modificare:

Come menzionato nei commenti, c'è una libreria disponibile su Google Code per raggiungere questo obiettivo:http://code.google.com/p/xeger

Guarda anche https://github.com/mifmif/Generex come suggerito da Mifmif

Messaggio originale:

In primo luogo, con un'espressione regolare abbastanza complessa, credo che ciò possa essere impossibile.Ma dovresti essere in grado di mettere insieme qualcosa per semplici espressioni regolari.

Se dai un'occhiata al codice sorgente della classe java.util.regex.Pattern, vedrai che utilizza una rappresentazione interna delle istanze di Node.Ciascuno dei diversi componenti del modello ha la propria implementazione di una sottoclasse Node.Questi nodi sono organizzati in un albero.

Producendo un visitatore che attraversa questo albero, dovresti essere in grado di chiamare un metodo generatore sovraccarico o una sorta di Builder che mette insieme qualcosa.

Altri suggerimenti

Xeger (Giava) è in grado di farlo anche:

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

È troppo tardi per aiutare il poster originale, ma potrebbe aiutare un nuovo arrivato. Generex è un'utile libreria Java che fornisce molte funzionalità per l'utilizzo di espressioni regolari per generare stringhe (generazione casuale, generazione di una stringa in base al suo indice, generazione di tutte le stringhe...).

Esempio :

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

Sono andato alla radice del rollio del mio Proprio libreria per quello (in C# ma dovrebbe essere facile da capire per uno sviluppatore Java).

Rxrdg è iniziato come soluzione a un problema di creazione di dati di test per un progetto di vita reale.L'idea di base è quella di sfruttare i modelli di validazione esistenti (espressioni regolari) per creare dati casuali conformi a tali modelli.In questo modo vengono creati dati casuali validi.

Non è così difficile scrivere un parser per semplici schemi regex.Usare un albero di sintassi astratto per generare stringhe dovrebbe essere ancora più semplice.

Sul podcast StackOverflow 11:

Spolsky:Sì.C'è anche un nuovo prodotto, se non vuoi utilizzare il Team System, i nostri amici di Redgate hanno un prodotto chiamato SQL Data Generator [http://www.red-gate.com/products/sql_data_generator/index.htm].Costa $ 295 e genera solo alcuni dati di test realistici.E fa cose come generare effettivamente città reali nella colonna delle città che esistono realmente, e poi quando le genera, troverà lo stato giusto, invece di sbagliare lo stato, o inserirà gli stati nelle città tedesche e cose del genere...sai, genera dati dall'aspetto piuttosto realistico.Non sono proprio sicuro di quali siano tutte le funzionalità.

Probabilmente non è quello che stai cercando, ma potrebbe essere un buon punto di partenza, invece di crearne uno tuo.

Non riesco a trovare nulla su Google, quindi suggerirei di affrontare il problema analizzando una determinata espressione regolare nelle unità di lavoro più piccole (\w, [x-x], \d, ecc.) e scrivendo alcuni metodi di base per supportare quelle frasi di espressione regolare.

Quindi per \w avresti un metodo getRandomLetter() che restituisce qualsiasi lettera casuale e avresti anche getRandomLetter(char startLetter, char endLetter) che ti dà una lettera casuale tra i due valori.

So che esiste già una risposta accettata, ma la sto utilizzando Generatore di dati di RedGate (quello menzionato nella risposta di Craig) e funziona MOLTO bene per tutto ciò che gli ho lanciato.È veloce e questo mi fa venir voglia di usare la stessa regex per generare i dati reali per cose come i codici di registrazione che questa cosa sputa.

Ci vuole una regex come:

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

e genera tonnellate di codici univoci come:

LLK-32U

Si tratta di un grosso algoritmo segreto che RedGate ha scoperto e siamo tutti sfortunati o è qualcosa che noi semplici mortali potremmo effettivamente fare?

Sono in volo e ho appena visto la domanda:Ho scritto la soluzione più semplice ma inefficiente e incompleta.Spero che possa aiutarti a iniziare a scrivere il tuo parser:

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

Dovrai scrivere il tuo parser, come ha fatto l'autore di String::Random (Perl).In effetti, non usa le espressioni regolari da nessuna parte in quel modulo, è proprio ciò a cui sono abituati i programmatori Perl.

D'altra parte, forse puoi dare un'occhiata la fonte, per avere alcune indicazioni.


MODIFICARE:Dannazione, Blair mi ha preceduto di 15 secondi.

È lungi dal supportare una regexp PCRE completa, ma ho scritto il seguente metodo Ruby per prendere una stringa simile a una regexp e produrne una variazione.(Per CAPTCHA basati sulla lingua.)

# 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

Questa domanda è molto vecchia, ma mi sono imbattuto in essa durante la mia ricerca, quindi includerò un paio di collegamenti per altri che potrebbero cercare la stessa funzionalità in altre lingue.

Se vuoi generare stringhe "critiche", potresti prendere in considerazione:

AIRONE http://elarson.pythonanywhere.com/che genera stringhe "malvagie" che coprono le tue espressioni regolari

MUTREX http://cs.unibg.it/mutrex/che genera stringhe di rilevamento errori mediante mutazione regex

Entrambi sono strumenti accademici (io sono uno degli autori di quest'ultimo) e funzionano abbastanza bene.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top