2009-10-16 20 views
26

Sí, has leído bien. Necesito algo que sea capaz de generar texto aleatorio de una expresión regular. Por lo tanto, el texto debe ser aleatorio, pero debe coincidir con la expresión regular. Parece que no existe, pero podría estar equivocado.¿Cómo puedo generar texto que coincida con una expresión regular de una expresión regular?

Just a un ejemplo: que la biblioteca sería capaz de tomar '[ab]*c' como entrada, y generar muestras tales como:

abc
abbbc
bac

etc.

Actualización: Yo mismo creé algo: Xeger. Consulte http://code.google.com/p/xeger/.

+1

Cool idea - interested to hear the results. – Ryall

+0

Esto de hecho sería bastante útil. – p3t0r

+0

creo que todos los selectores "... o más" tendrían que estar limitada a pesar de o usted podría terminar con 1.000.000 palabras de caracteres: S – Ryall

Respuesta

16

Acabo de crear una biblioteca para hacer esto hace un minuto. Está alojado aquí: http://code.google.com/p/xeger/. Lea atentamente las instrucciones antes de usarlo. (. Sobre todo la que se refiere a la descarga de otra biblioteca requerido) ;-)

Esta es la forma en que lo utilice:

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

No tengo conocimiento de dicha biblioteca. Si usted está interesado en escribir uno mismo, entonces estos son probablemente los pasos que tendrá que tomar:

  1. Escribir un analizador de expresiones regulares (es posible que desee comenzar con una clase restringida de expresiones regulares) .

  2. Usa el resultado para construir un NFA.

  3. (Opcional) Convierta el NFA a DFA.

  4. Cruce aleatoriamente el autómata resultante desde el estado de inicio a cualquier estado de aceptación, mientras almacena los caracteres producidos por cada transición.

El resultado es una palabra que es aceptada por el regex original. Para obtener más información, consulte, por ejemplo, Converting a Regular Expression into a Deterministic Finite Automaton.

+0

He estado buscando una biblioteca que crearía un NFA a partir de regex en Java. Sé que lo anterior funcionaría, ya que solía hacer eso en Javascript hace siglos. –

+0

supongo que esto valdría la pena echar un vistazo a: http://www.brics.dk/~amoeller/automaton/ –

+0

he implementado Xeger basado en la biblioteca menciono anteriormente. –

2

Here'sa fewimplementations de una bestia, pero ninguno de ellos en Java (y todos, excepto el de código cerrado Microsoft muy limitados en su soporte de las funciones de expresiones regulares).

2

basado en la solución de Wilfred Springer junto con http://www.brics.dk/~amoeller/automaton/ construyo otro generador. No usa recursividad. Toma como entrada la longitud de cadena mínima de patter/regularExpression y la longitud de cadena máxima. El resultado es una cadena aceptada entre la longitud mínima y máxima. También permite algunas de las "clases de caracteres de mano corta" de XML. Utilizo esto para un generador de muestras XML que construye Cadena válida para facetas.

public static final String generate(final String pattern, final int minLength, final int maxLength) { 
    final String regex = pattern 
      .replace("\\d", "[0-9]")  // Used d=Digit 
      .replace("\\w", "[A-Za-z0-9_]") // Used d=Word 
      .replace("\\s", "[ \t\r\n]"); // Used s="White"Space 
    final Automaton automaton = new RegExp(regex).toAutomaton(); 
    final Random random = new Random(System.nanoTime()); 
    final List<String> validLength = new LinkedList<>(); 
    int len = 0; 
    final StringBuilder builder = new StringBuilder(); 
    State state = automaton.getInitialState(); 
    Transition[] transitions; 
    while(len <= maxLength && (transitions = state.getSortedTransitionArray(true)).length != 0) { 
     final int option = random.nextInt(transitions.length); 
     if (state.isAccept() && len >= minLength && len <= maxLength) validLength.add(builder.toString()); 
     final Transition t = transitions[option]; // random transition 
     builder.append((char) (t.getMin()+random.nextInt(t.getMax()-t.getMin()+1))); len ++; 
     state = t.getDest(); 
    } 
    if(validLength.size() == 0) throw new IllegalArgumentException(automaton.toString()+" , "+minLength+" , "+maxLength); 
    return validLength.get(random.nextInt(validLength.size())); 
} 
Cuestiones relacionadas