Pergunta

Estou escrevendo um utilitário Java que me ajuda a gerar muitos dados para testes de desempenho.Seria realmente legal poder especificar um regex para Strings para que meu gerador produza coisas que correspondam a isso.Existe algo já assado que eu possa usar para fazer isso?Ou existe uma biblioteca que me leva até lá?

Obrigado

Foi útil?

Solução

Editar:

Conforme mencionado nos comentários, existe uma biblioteca disponível no Google Code para conseguir isso:http://code.google.com/p/xeger

Veja também https://github.com/mifmif/Generex como sugerido por Mifmif

Mensagem original:

Em primeiro lugar, com um regexp complexo o suficiente, acredito que isso pode ser impossível.Mas você deve ser capaz de montar algo para expressões regulares simples.

Se você der uma olhada no código fonte da classe java.util.regex.Pattern, verá que ele usa uma representação interna de instâncias do Node.Cada um dos diferentes componentes do padrão possui sua própria implementação de uma subclasse Node.Esses nós são organizados em uma árvore.

Ao produzir um visitante que percorre essa árvore, você poderá chamar um método gerador sobrecarregado ou algum tipo de construtor que remende algo.

Outras dicas

Xeger (Java) é capaz de fazer isso também:

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

É tarde demais para ajudar o autor da postagem original, mas pode ajudar um recém-chegado. Generex é uma biblioteca Java útil que fornece muitos recursos para usar regexes para gerar strings (geração aleatória, geração de uma string com base em seu índice, geração de todas as strings...).

Exemplo :

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

Eu cheguei à raiz de rolar meu ter biblioteca para isso (em c#, mas deve ser fácil de entender para um desenvolvedor Java).

O Rxrdg começou como uma solução para um problema de criação de dados de teste para um projeto da vida real.A ideia básica é aproveitar os padrões de validação existentes (expressão regular) para criar dados aleatórios que estejam em conformidade com tais padrões.Dessa forma, dados aleatórios válidos são criados.

Não é tão difícil escrever um analisador para padrões regex simples.Usar uma árvore de sintaxe abstrata para gerar strings deve ser ainda mais fácil.

No podcast stackoverflow 11:

Polsky:Sim.Há um novo produto também, se você não quiser usar o Team System, nossos amigos da Redgate têm um produto chamado SQL Data Generator [http://www.red-gate.com/products/sql_data_generator/index.htm].Custa US$ 295 e apenas gera alguns dados de teste realistas.E faz coisas como realmente gerar cidades reais na coluna de cidades que realmente existem, e então, quando as gera, acertará o estado, em vez de errar o estado, ou colocará estados em cidades alemãs e coisas assim...você sabe, ele gera dados de aparência bastante realista.Não tenho certeza de quais são todos os recursos.

Provavelmente não é isso que você está procurando, mas pode ser um bom ponto de partida, em vez de criar o seu próprio.

Não consigo encontrar nada no Google, então sugiro resolver o problema analisando uma determinada expressão regular nas menores unidades de trabalho (\w, [x-x], \d, etc) e escrevendo alguns métodos básicos para apoiar aquelas frases de expressão regular.

Então, para \w você teria um método getRandomLetter() que retorna qualquer letra aleatória, e você também teria getRandomLetter(char startLetter, char endLetter) que fornece uma letra aleatória entre os dois valores.

Eu sei que já existe uma resposta aceita, mas tenho usado Gerador de dados do RedGate (aquele mencionado na resposta de Craig) e funciona MUITO bem para tudo que eu joguei nele.É rápido e isso me deixa com vontade de usar o mesmo regex para gerar dados reais para coisas como códigos de registro que essa coisa cospe.

É preciso um regex como:

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

e gera toneladas de códigos exclusivos como:

LLK-32U

Isso é algum grande algoritmo secreto que RedGate descobriu e estamos todos sem sorte ou é algo que nós, meros mortais, realmente poderíamos fazer?

Estou em vôo e acabei de ver a pergunta:Escrevi a solução mais fácil, mas ineficiente e incompleta.Espero que possa ajudá-lo a começar a escrever seu próprio analisador:

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

Você terá que escrever seu próprio analisador, como fez o autor de String::Random (Perl).Na verdade, ele não usa expressões regulares em nenhum lugar desse módulo, é apenas com o que os codificadores Perl estão acostumados.

Por outro lado, talvez você possa dar uma olhada a fonte, para obter algumas dicas.


EDITAR:Droga, Blair me venceu por 15 segundos.

Está longe de suportar um regexp PCRE completo, mas escrevi o seguinte método Ruby para pegar uma string semelhante a um regexp e produzir uma variação dela.(Para CAPTCHA baseado em 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 pergunta é muito antiga, mas me deparei com ela em minha própria pesquisa, por isso incluirei alguns links para outras pessoas que possam estar procurando a mesma funcionalidade em outros idiomas.

Se você deseja gerar strings "críticas", considere:

Garça http://elarson.pythonanywhere.com/que gera strings "malignas" cobrindo suas expressões regulares

MUTREX http://cs.unibg.it/mutrex/que gera strings de detecção de falhas por mutação regex

Ambas são ferramentas acadêmicas (sou um dos autores desta última) e funcionam razoavelmente bem.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top