Pregunta

Estoy escribiendo una utilidad Java que me ayuda a generar una gran cantidad de datos para pruebas de rendimiento.Sería en realidad Es genial poder especificar una expresión regular para cadenas para que mi generador escupe cosas que coincidan con esto.¿Hay algo ya preparado que pueda usar para hacer esto?¿O hay una biblioteca que me lleva hasta allí?

Gracias

¿Fue útil?

Solución

Editar:

Como se menciona en los comentarios, hay una biblioteca disponible en Google Code para lograr esto:http://code.google.com/p/xeger

Ver también https://github.com/mifmif/Generex como lo sugiere mifmif

Mensaje original:

En primer lugar, con una expresión regular lo suficientemente compleja, creo que esto puede ser imposible.Pero deberías poder armar algo para expresiones regulares simples.

Si echas un vistazo al código fuente de la clase java.util.regex.Pattern, verás que utiliza una representación interna de instancias de Node.Cada uno de los diferentes componentes del patrón tiene su propia implementación de una subclase de Nodo.Estos Nodos están organizados en un árbol.

Al producir un visitante que recorra este árbol, debería poder llamar a un método generador sobrecargado o algún tipo de constructor que improvise algo.

Otros consejos

Xeger (Java) es capaz de hacerlo también:

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

Es demasiado tarde para ayudar al cartel original, pero podría ayudar a un recién llegado. genérico es una biblioteca Java útil que proporciona muchas características para usar expresiones regulares para generar cadenas (generación aleatoria, generación de una cadena basada en su índice, generación de todas las cadenas...).

Ejemplo :

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

He ido a la raíz de rodar mi propio biblioteca para eso (en c# pero debería ser fácil de entender para un desarrollador de Java).

Rxrdg comenzó como una solución a un problema de creación de datos de prueba para un proyecto de la vida real.La idea básica es aprovechar los patrones de validación existentes (expresiones regulares) para crear datos aleatorios que se ajusten a dichos patrones.De esta manera se crean datos aleatorios válidos.

No es tan difícil escribir un analizador para patrones de expresiones regulares simples.Usar un árbol de sintaxis abstracta para generar cadenas debería ser aún más fácil.

En el podcast 11 de stackoverflow:

Spolsky:Sí.También hay un producto nuevo, si no desea utilizar Team System, nuestros amigos de Redgate tienen un producto llamado SQL Data Generator [http://www.red-gate.com/products/sql_data_generator/index.htm].Cuesta $ 295 y solo genera algunos datos de prueba realistas.Y hace cosas como generar ciudades reales en la columna de ciudades que realmente existen, y luego, cuando las genera, obtendrá el estado correcto, en lugar de equivocarse, o colocar estados en ciudades alemanas y cosas como...ya sabes, genera datos de apariencia bastante realista.No estoy realmente seguro de cuáles son todas las características.

Probablemente esto no sea lo que estás buscando, pero podría ser un buen punto de partida, en lugar de crear el tuyo propio.

Parece que no puedo encontrar nada en Google, por lo que sugeriría abordar el problema analizando una expresión regular dada en las unidades de trabajo más pequeñas (\w, [x-x], \d, etc.) y escribiendo algunos métodos básicos para soportar esas frases de expresiones regulares.

Entonces, para \w tendrías un método getRandomLetter() que devuelve cualquier letra aleatoria, y también tendrías getRandomLetter(char startLetter, char endLetter) que te da una letra aleatoria entre los dos valores.

Sé que ya hay una respuesta aceptada, pero he estado usando Generador de datos de RedGate (el mencionado en la respuesta de Craig) y funciona REALMENTE bien para todo lo que le he lanzado.Es rápido y eso me deja con ganas de usar la misma expresión regular para generar datos reales para cosas como los códigos de registro que escupe esta cosa.

Se necesita una expresión regular como:

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

y genera toneladas de códigos únicos como:

LLK-32U

¿Es este un gran algoritmo secreto que RedGate descubrió y no tenemos suerte o es algo que nosotros, simples mortales, realmente podríamos hacer?

Estoy en vuelo y acabo de ver la pregunta:He escrito la solución más fácil pero ineficiente e incompleta.Espero que te pueda ayudar a empezar a escribir tu propio analizador:

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

Tendrás que escribir tu propio analizador, como lo hizo el autor de String::Random (Perl).De hecho, no usa expresiones regulares en ninguna parte de ese módulo, es simplemente a lo que están acostumbrados los codificadores de Perl.

Por otro lado, tal vez puedas echar un vistazo a la fuente, para obtener algunos consejos.


EDITAR:Maldita sea, Blair me ganó por 15 segundos.

Está lejos de admitir una expresión regular PCRE completa, pero escribí el siguiente método Ruby para tomar una cadena similar a una expresión regular y producir una variación de ella.(Para CAPTCHA basado en idioma).

# 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

Esta pregunta es muy antigua, pero la encontré en mi propia búsqueda, por lo que incluiré un par de enlaces para otras personas que puedan estar buscando la misma funcionalidad en otros idiomas.

Si desea generar cadenas "críticas", puede considerar:

GARCETA http://elarson.pythonanywhere.com/que genera cadenas "malvadas" que cubren sus expresiones regulares

MUTREX http://cs.unibg.it/mutrex/que genera cadenas de detección de fallas mediante mutación de expresiones regulares

Ambas son herramientas académicas (soy uno de los autores de la última) y funcionan razonablemente bien.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top