Par exemple, étant donné la chaîne "2009/11/12", je veux obtenir l'expression régulière ("\ d {2}/d {2}/d {4}"), je vais donc pouvoir faire correspondre "2001/01/02 "aussi.
Y a-t-il quelque chose qui fait ça? Quelque chose de similaire? Une idée sur la façon de le faire?
Il existe text2re , un générateur gratuit de "regex by example" 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 de regex automatique qui fonctionne correctement sans intervention de l'utilisateur, car cela demanderait à la machine de savoir ce que vous voulez.
Notez que text2re utilise une approche de la génération d’expression régulière, généralisée et très généralisée, basée sur des modèles. Les expressions qu’il génère fonctionnent, mais elles sont beaucoup plus complexes que les expressions équivalentes fabriquées à la main. Ce n'est pas un bon outil pour apprendre les expressions régulières, car il fait un travail assez moche pour donner des exemples.
Par exemple, la chaîne "2009/11/12"
serait reconnue comme un motif yyyymmdd
, ce qui est utile. L'outil le transforme en ce 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 fabriqué à la main ne prendrait que les deux cinquièmes de celui-ci (50 caractères):
([12]\d{3})[-:/.](0?\d|1[0-2])[-:/.]([0-2]?\d|3[01])\b
Il n'est pas possible d'écrire une solution générale à votre problème. Le problème est que tout 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 pouvez faire est d’écrire vous-même un tel générateur qui convient parfaitement à votre problème, mais une solution générale ne sera pas possible.
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, mais vous pouvez lui donner divers indices et cela facilitera la vie. Quelques exemples suivront.
Une sortie lisible traduisant le résultat serait également très utile. Quelque chose comme:
Peut-être pourrions-nous créer un "traducteur arrière" avec un langage de type SQL pour créer un regex, au lieu de le créer en geekish.
Voici quelques exemples 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 texte ou le saisissez, l'ajout à l'expression régulière serait également possible. Tout d’abord, vous marquez une date ("échantillon") et choisissez si ce texte est déjà formaté ou si vous construisez un format, ainsi que le type de format: texte libre, texte formaté, date, GUID ou Choisir ... parmi les formats existants (que vous pouvez stocker dans la bibliothèque).
Permet de concevoir une spécification pour cela, et de le rendre open source ... Quelqu'un veut-il rejoindre?
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\d
ISBN 332212 ->\w\w\w\w\d\d\d\d\d\d\d
Comme déjà souligné par d'autres, une solution générale à ce problème est impossible. Cette classe est applicable uniquement dans quelques contextes
cela ressemble à un problème d’apprentissage automatique. Vous devrez disposer de plus d'un exemple (beaucoup plus) et indiquer si chaque exemple est considéré comme une correspondance ou non.
Non, vous ne pouvez pas obtenir une expression régulière qui corresponde à ce que vous voulez, car elle ne contiendrait pas d’informations sémantiques sur l’entrée (c’est-à-dire qu’elle aurait besoin de savoir qu’elle génère une expression régulière pour les dates). Si le problème concerne uniquement les dates, je vous recommanderais d'essayer plusieurs expressions régulières et de voir si l'une d'elles correspond à toutes.
Je ne sais pas si cela est possible, du moins pas sans exemples de chaînes et d'algorithmes d'apprentissage.
Il y a beaucoup de regex 'qui correspondraient et il n'est pas possible pour un simple algorithme de choisir le' bon '. Vous devez lui donner des délimiteurs ou d'autres éléments à rechercher, vous pouvez donc aussi bien écrire vous-même la regex.
Loreto fait à peu près cela. C'est une implémentation open source utilisant la plus longue sous-chaîne commune pour générer les expressions régulières. A besoin de plusieurs exemples de cours, cependant.
En plus de fournir à l'algorithme d'apprentissage des exemples de "bonne" entrée, vous pouvez le nourrir "mauvais" afin qu'il sache quoi ne pas rechercher. Aucune lettre dans un numéro de téléphone, par exemple.
Je ne me souviens pas du nom mais si ma théorie du calcul des cellules me sert correctement, c'est impossible en théorie :)
Je n'ai rien trouvé qui puisse le faire, 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 "date" générateur d'expression régulière ". Une fois que je serai satisfait des tests unitaires, je le publierai, 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 géniales, mais celui-ci était sssssssssoooo boiteux :))