Étant donné une chaîne, générez une expression régulière qui peut analyser des chaînes* similaires *


Par exemple, étant donné la chaîne "2009/11/12", je veux obtenir l'expression régulière ("\d{2}/d{2}/d{4}"), donc je pourrai également faire correspondre "2001/01/02".

Y a-t-il quelque chose qui fait cela? Quelque chose de semblable? Toute idée de " quant à comment le faire?

Author: unwind, 2009-04-22

11 answers

Il existe text2re, un générateur "regex by example" gratuit basé sur le Web.

Je ne pense pas que cela soit disponible dans le code source, cependant. J'ose dire qu'il n'y a pas de générateur regex automatique qui fonctionne correctement sans intervention de l'utilisateur, car cela nécessiterait que la machine sache ce que vous voulez.


Notez que text2re utilise une approche basée sur un modèle, modularisée et très généralisée pour la génération d'expressions régulières. Les expressions qu'il génère fonctionnent, mais elles sont beaucoup plus complexe que l'expression artisanale équivalente. Ce n'est pas un bon outil pour apprendre des expressions régulières car il fait un travail assez moche pour définir des exemples.

Par exemple, la chaîne "2009/11/12" serait reconnue comme un motif yyyymmdd, ce qui est utile. L'outil le transforme ence monstre de 125 caractères:

((?:(?:[1]{1}\d{1}\d{1}\d{1})|(?:[2]{1}\d{3}))[-:\/.](?:[0]?[1-9]|[1][012])[-:\/.](?:(?:[0-2]?\d{1})|(?:[3][01]{1})))(?![\d])

L'équivalent fait à la main ne prendrait que les deux cinquièmes de cela (50 caractères):

([12]\d{3})[-:/.](0?\d|1[0-2])[-:/.]([0-2]?\d|3[01])\b
 25
Author: Tomalak, 2012-12-05 22:47:25

Il n'est pas possible d'écrire une solution générale pour votre problème. Le problème est que n'importe quel générateur ne saurait probablement pas ce que vous voulez vérifier, par exemple "2312/45/67" devrait-il également être autorisé? Qu'en est-il de "2009.11.12"?

Ce que vous pourriez faire, c'est écrire vous-même un tel générateur qui convient à votre problème exact, mais une solution générale ne sera pas possible.

 11
Author: B.E., 2009-04-22 09:08:58

Excusez-moi, mais ce que vous appelez tous impossible est clairement une tâche réalisable. Il ne sera pas en mesure de donner des résultats pour TOUS les exemples, et peut-être pas les meilleurs résultats, mais vous pouvez lui donner divers conseils, et cela rendra la vie facile. Quelques exemples à suivre.

Une sortie lisible traduisant le résultat serait également très utile. Quelque chose comme:

  • "Rechercher: un mot commençant par une lettre non numérique et se terminant par la chaîne: "ing".
  • ou: Rechercher for: texte qui contient bbb, suivi quelque part de zzz
  • ou: *Rechercher: un modèle qui a l'air tellement "aa/bbbb/cccc" où "/" est un séparateur, "aa" est à deux chiffres, "bbbb" est un mot de n'importe quelle longueur et "cccc" quatre chiffres entre 1900 et 2020 *

Peut-être que nous pourrions faire un "back translator" avec un type de langage SQL pour créer regex, au lieu de le créer en geekish.

Voici quelques exemples qui sont faisables:

class Hint: 
  Properties: HintType, HintString
  enum HintType { Separator, ParamDescription, NumberOfParameters }
  enum SampleType { FreeText, DateOrTime, Formatted, ... }
  public string RegexBySamples( List<T> samples, 
         List<SampleType> sampleTypes, 
         List<Hint> hints, 
         out string GeneralRegExp, out string description, 
         out string generalDescription)...

regex = RegExpBySamples( {"11/November/1999", "2/January/2003"}, 
                     SampleType.DateOrTime, 
                     new HintList( HintType.NumberOfParameters, 3 ));

regex = RegExpBySamples( "123-aaaaJ-1444", 
                         SampleType.Format, HintType.Seperator, "-" );

Une interface graphique où vous marquez un échantillon texte ou entrez-le, ajouter à l'expression régulière serait également possible. Vous marquez d'abord une date (l ' "échantillon"), et choisissez si ce texte est déjà formaté, ou si vous construisez un format, également quel est le type de format: texte libre, texte formaté, date, GUID ou Choisissez... de formats existants (que vous pouvez stocker dans la bibliothèque).

Permet de concevoir une spécification pour cela et de la rendre open source... Quelqu'un veut nous rejoindre?

 4
Author: pashute, 2015-01-20 11:36:39

J'ai essayé une approche très naïve:

class RegexpGenerator {

    public static Pattern generateRegexp(String prototype) {
        return Pattern.compile(generateRegexpFrom(prototype));
    }

    private static String generateRegexpFrom(String prototype) {
        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < prototype.length(); i++) {
            char c = prototype.charAt(i);

            if (Character.isDigit(c)) {
                stringBuilder.append("\\d");
            } else if (Character.isLetter(c)) {
                stringBuilder.append("\\w");
            } else { // falltrought: literal
                stringBuilder.append(c);
            }
        }

        return stringBuilder.toString();
    }

    private static void test(String prototype) {
        Pattern pattern = generateRegexp(prototype);
        System.out.println(String.format("%s -> %s", prototype, pattern));

        if (!pattern.matcher(prototype).matches()) {
            throw new AssertionError();
        }
    }

    public static void main(String[] args) {
        String[] prototypes = {
            "2009/11/12",
            "I'm a test",
            "me too!!!",
            "124.323.232.112",
            "ISBN 332212"
        };

        for (String prototype : prototypes) {
            test(prototype);
        }
    }
}

Sortie:

2009/11/12 -> \d\d\d\d/\d\d/\d\d
Je suis un test -> \w\w \w \w\w\w\w
Moi aussi!!! -> \w\w \w\w\w!!!
124.323.232.112 -> \d\d\d.\d\d\d.\d\d\d.\d\d\d
ISBN 332212 -> \w\w\w\w \d\d\d\d\d\d

Comme d'autres l'ont déjà souligné, une solution générale à ce problème est impossible. Cette classe n'est applicable que dans quelques contextes

 3
Author: dfa, 2009-04-22 13:25:03

Non, vous ne pouvez pas obtenir une expression régulière qui correspond à ce que vous voulez de manière fiable, car l'expression régulière ne contiendrait pas d'informations sémantiques sur l'entrée (c'est-à-dire qu'elle devrait savoir qu'elle génère une expression régulière pour les dates). Si le problème concerne uniquement les dates, je recommanderais d'essayer plusieurs expressions régulières et de voir si l'une d'entre elles correspond à toutes.

 1
Author: soulmerge, 2009-04-22 09:11:13

Je ne sais pas si cela est possible, du moins pas sans de nombreux exemples de chaînes et un algorithme d'apprentissage.

Il y a beaucoup de regex' qui correspondraient et il n'est pas possible pour un algorithme simple de choisir le 'bon'. Vous auriez besoin de lui donner des délimiteurs ou d'autres choses à rechercher, donc vous pourriez aussi bien écrire l'expression régulière vous-même.

 1
Author: Cogsy, 2009-04-22 09:11:41

Ressemble à un problème d'apprentissage automatique. Vous devrez avoir plus d'un exemple en main (beaucoup plus) et une indication de si chaque exemple est considéré comme une correspondance ou non.

 1
Author: Kyle Dyer, 2009-04-22 13:47:10

Loreto fait à peu près cela. C'est une implémentation open source utilisant la ou les sous-chaînes les plus longues communes pour générer les expressions régulières. Besoin de plusieurs exemples, cependant.

 1
Author: , 2009-07-21 11:29:04

Je ne me souviens pas du nom mais si ma théorie des cellules de calcul me sert correctement, c'est impossible en théorie:)

 0
Author: MahdeTo, 2009-04-22 09:14:23

Je n'ai rien trouvé qui le fasse , mais puisque le domaine du problème est relativement petit (vous seriez surpris de voir combien de personnes utilisent les formats de date les plus étranges) , j'ai pu écrire une sorte de "générateur d'expression régulière de date". Une fois que je suis satisfait des tests unitaires , je le publierai - juste au cas où quelqu'un aurait besoin de quelque chose du genre.

Merci à tous ceux qui ont répondu (le gars avec le (.* ) exclus-les blagues sont super, mais celui-ci était ssssssssssoooo boiteux :) )

 0
Author: Yossale, 2009-04-27 08:57:29

En plus de nourrir l'algorithme d'apprentissage des exemples de "bonne" entrée, vous pouvez le nourrir "mauvaise" entrée afin qu'il sache ce qu'il ne faut pas chercher. Pas de lettres dans un numéro de téléphone, par exemple.

 0
Author: JDrago, 2011-06-17 05:16:25