2008-08-22 35 views
84

Estoy escribiendo una utilidad de Java que me ayuda a generar una gran cantidad de datos para las pruebas de rendimiento. Sería realmente genial para poder especificar una expresión regular para cadenas para que mi generador escupe cosas que coinciden con esto. ¿Hay algo allí ya horneado que pueda usar para hacer esto? ¿O hay una biblioteca que me lleva la mayor parte del camino hasta allí?Uso de Regex para generar cadenas en lugar de combinarlas

Gracias

+0

Aquí hay una [biblioteca java] útil (https://github.com/mifmif/Generex) que proporciona muchas características para usar expresiones regulares para generar cadenas (generación aleatoria, generar cadenas basadas en su índice, generar todas las cadenas ...) verificarlo fuera [aquí] (https://github.com/mifmif/Generex) – Mifmif

Respuesta

30

Editar:

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

Véase también https://github.com/mifmif/Generex como sugiere Mifmif

mensaje original :

Primero, ingenio h una expresión regular lo suficientemente compleja, creo que esto puede ser imposible. Pero deberías ser capaz de armar algo para expresiones regulares simples.

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

Al producir un visitante que atraviesa este árbol, debería ser capaz de llamar a un método de generador sobrecargado o algún tipo de generador que improvise algo juntos.

+4

En realidad, hay una biblioteca Java: http://code.google.com/p/xeger/ –

+0

No estoy seguro de que Xeger sea tan bueno. No puede manejar clases de caracteres. No reconoce un simple '[\ w]'. Una mirada a la última línea de [su wiki] (https://code.google.com/archive/p/xeger/wikis/XegerLimitations.wiki) nos dice eso. El enlace –

1

Vas a tener que escribir su propio analizador, como el autor de los Hilos :: Random (Perl) lo hizo. De hecho, él no usa expresiones regulares en ningún lado en ese módulo, es justo a lo que los perl-codificadores están acostumbrados.

Por otro lado, tal vez pueda echar un vistazo a the source, para obtener algunos consejos.


EDIT: Damn, blair me ganó al golpe por 15 segundos.

4

Visual Studio Team System incluye algo como esto. Check it out

No fue de mucha ayuda para Java, así que lo siento.

3

En el podcast stackoverflow 11:

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

Esto probablemente no es lo que está buscando, pero podría ser un buen punto de partida, en lugar de crear el suyo propio.

Parece que no encuentro nada en google, por lo que sugiero abordar el problema analizando una expresión regular dada en las unidades de trabajo más pequeñas (\ w, [xx], \ d, etc.) y escribiendo algunas métodos básicos para apoyar esas frases de expresiones regulares.

Así que para \ w tendría un método getRandomLetter() que devuelve cualquier letra al azar, y también tendría getRandomLetter (char startLetter, char endLetter) que le da una letra aleatoria entre los dos valores.

2

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

Se necesita una expresión regular como:

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

y genera toneladas de códigos únicas como:

LLK-32U 

Es esto una gran algoritmo secreto que Redgate descubierto y estamos todos fuera de ¿Suerte o es algo que los simples mortales en realidad podríamos hacer?

0

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

# 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
4

he ido rodando la raíz de mi biblioteca own para que (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 simples de expresiones regulares. Usar un árbol de sintaxis abstracta para generar cadenas debería ser aún más fácil.

+0

ya no apunta al repositorio. Me gustaría ir con https://www.openhub.net/p/rxrdg. La solución no se construye, sin embargo? – Veverke

18

Xeger (Java) es capaz de hacerlo así:

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

Xeger funciona muy bien. PERO asegúrese de tener el [autómata tarro] (https://mvnrepository.com/artifact/dk.brics.automaton/automaton/1.11-8) en la ruta de la clase o en su pom/gradle –

1

estoy en vuelo y acabo de ver la pregunta: He escrito más fácil, pero la solución ineficiente e incompleta. Espero que le puede ayudar a comenzar a escribir su 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); 
} 
+0

Es posible que desee indicar qué tipo de cadenas se usan como entrada de patrón. Antes que nada, no es tan fácil determinar tales cosas desde el código fuente. Segundo, si hay algún error o falta de claridad en el código fuente, no hay forma de ver si son intencionales o no. –

+0

StringTokenizer es una clase heredada que se conserva por razones de compatibilidad, aunque se desaconseja su uso en el nuevo código. Se recomienda que cualquiera que busque esta funcionalidad use el método de división de String o el paquete java.util.regex en su lugar. – Rohit

10

Es demasiado tarde para ayudar a su creador original, pero podría ayudar a un recién llegado. Generex es una biblioteca de 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 
+5

Parece que Generex es su propio proyecto. ¿Le importaría mencionar en su publicación que este es su propio proyecto, según las reglas [aquí] (http://stackoverflow.com/help/behavior)? –

-1

Si desea generar cadenas "críticos", es posible que desee considerar:

EGRET http://elarson.pythonanywhere.com/ que genera cadenas "malos" que cubre sus expresiones regulares

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

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

-1

Esta pregunta es muy antigua, pero me topé con ella en mi propia búsqueda, por lo que incluiré un par de enlaces para otras personas que podrían estar buscando la misma funcionalidad en otros idiomas.

Cuestiones relacionadas