2009-07-14 1 views
2

Disons que nous avons deux expressions régulières:Comment vérifier la pertinence d'un regexp?

1234.* 

et

.* 

Entrée:

1234567 

Il est évident que les deux match mais 1234. * correspond mieux puisqu'il est plus spécifique. c'est-à-dire est plus pertinent. Existe-t-il un moyen standard de vérifier ce qui est le plus pertinent?

modifier:

Quelques précisions. Je veux prendre des décisions en vérifiant quelle expression correspond le mieux à l'entrée. Dans ce cas, je ne fais que correspondre des nombres.

Exemple avec les numéros de téléphone:

Entrée:

31882481337 

Nous avons une règle pour chacune des expressions régulières suivantes:

31.* 
.* 

Dans ce scénario je voudrais que la règle soit utilisé qui est lié à 31. * parce que c'est plus spécifique pour l'entrée donnée. Si je n'utilisais pas regexps il serait facile, parce que je pouvais utiliser un mécanisme de notation pour vérifier combien il correspond, mais ces règles peuvent avoir des regexps plus avancés, comme:

31[89].* 
+0

Semble plutôt subjective. Pouvez-vous clarifier comment la "pertinence" serait quantifiée? Peut-être pas dans cet exemple, mais dans des cas plus complexes, on pourrait dire "plus pertinent". –

+0

@Codebender: J'espère que je me suis fait plus clair maintenant :-) –

+0

Est-ce que 31 [89]. * Est plus ou moins spécifique que 31 [2468] {3}. *? Qu'en est-il de 31?{9} vs 31 \ d {8,10}? –

Répondre

1

Cela fait longtemps que je n'ai pas posé cette question, mais je voulais vous faire savoir ce que je suis venu à la fin. Je suis allé pour une approche beaucoup plus simple, j'ai juste ajouté un facteur de poids à mes expressions régulières. Donc, vous pourriez dire que j'ai défini la pertinence de l'expression régulière moi-même au lieu d'essayer de la définir en utilisant des expressions régulières:

Expression  Relevance 
31.*    1 
.*    0 
1

un facteur que je peux penser est de savoir si un langage est infini ou non infini. non infini est certainement plus pertinent que l'infini car il y a un nombre fini de mots acceptables dans la langue. Si vous mesurez des langages infinis comme vos exemples, tous les deux continuent éternellement et vous pouvez continuer à compter chaque mot dans la langue jusqu'à ce que vous soyez bleus dans le visage, vous n'aboutirez jamais à une conclusion.

jusqu'à ce que vous considérez que la langue du premier regex est un sous-ensemble correct de la langue de la seconde. Ensuite, vous pourriez dire que l'un est plus pertinent.

Je ne suis pas sûr de standard quoi que ce soit de la façon de mesurer la pertinence regex. Pour exposer l'idée de sous-ensembles appropriés, vous pouvez vous demander quelle est votre langue et votre expression régulière accepte-t-elle des mots en dehors de cela? Votre expression peut encore fonctionner, mais elle contient un plus grand nombre de mots que vous n'en aviez l'intention ... bien sûr, cela n'a pas d'importance si votre contribution est contrôlée, mais c'est une façon de mesurer la pertinence. est-ce qu'il accepte ma langue exactement?

vôtre est un bon exemple, peut-être que vous voulez accepter les numéros commençant par 1234. 1234.* fonctionne comme un charme ... mais ce n'est pas la langue que vous avez spécifiée. `1234 \ d * est plus spécifique et correspond à votre langue exactement comme vous l'avez spécifié ... étant ainsi plus pertinent.

mais tout cela d'un point de vue purement théorique et ne vous aidera probablement pas beaucoup à déterminer si une regex est meilleure qu'une autre.

4

Je pense qu'il n'y a pas de moyen facile de le faire. Si vous regardez des exemples plus complexes, vous réaliserez bientôt qu'il est assez difficile de définir exactement «plus pertinent» du tout. Toutes les choses comme les assertions et les références arrières entrent en jeu.

Je peux penser à deux façons d'estimer grossièrement la «pertinence».

  1. De modifier aléatoirement l'entrée et de comparer le nombre de modifications entraînant l'échec de chaque expression.

  2. Analysez les expressions itselve. Comptez et comapre le nombre de symboles terminaux vs wildcards, le nombre d'assertion et tout ce que vous aimez.

esspecially dans la deuxième solution vous devez savoir que de nombreuses alternatives, qui ne sont pas utilisés par la mise en correspondance réelle, pourrait rendre le résultat hors de propos.

h.*|verylongtext|anotherverylongtext 

hell.*|v.* 

cas de « bonjour », la deuxième expression est « plus pertinent », mais le premier contient des symboles beaucoup plus terminaux et pourrait obtenir un classement beaucoup mieux par la seconde solution. Mais pour faire correspondre "verylongtext" le premier est "plus pertinent". Cela montre que la "pertinence" dépend fortement de l'entrée réelle et que vous devrez analyser le chemin de correspondance réel - ce qui est implicitement fait par la première solution. Mais modifier aléatoirement l'entrée est une tâche assez difficile car l'espace des entrées possibles est assez important. Je pense que ça ne marchera pas très bien aussi.

0

Je ne sais pas si "pertinence" est le vrai problème. Chacun est pertinent, et chacun correspondra à "1234567", comme vous le suggérez. Comme vous le dites aussi, cependant, un ("1234. *") est plus spécifique. Avec des expressions régulières, la spécificité est grande (dans un cas simple comme celui-ci), et parfois vous pouvez vous concentrer sur ce point jusqu'à ce que vous réalisiez que vous n'en aviez pas besoin (une regex) après tout. Règle n ° 1 des expressions régulières: Ne les utilisez pas si vous ne le devez pas. Par exemple, pour correspondre « 1234567 », je partirais avec:

$source = '1234567'; 
if (stripos($source, '1234') === 0) { 
    $foo = substr($source, 4); 
    // $source began with '1234' and $foo holds the rest 
} else { 
    // it didn't begin with '1234' 
} 

C'est un exemple de PHP, mais l'idée est que, puisque vous avez peaufiné votre valeur acceptée dans la bien, vous faites même pas besoin de PCRE plus. "Pertinence" ne vous dira pas vraiment beaucoup sur une expression régulière (comment définiriez-vous "pertinence" dans ce contexte?), Cependant je pense que la spécificité est une mesure plus objective, et être capable d'utiliser des fonctions de chaînes non-regex comme diable soit très mesurable spécifique (en fait, c'est booléen - y at-il une expression régulière ou non?). En dehors de la possibilité de réduire l'expression régulière de l'équation: Pour mesurer la spécificité d'une expression régulière donnée, comparez simplement (heuristiquement, si nécessaire) combien de valeurs différentes satisferaient l'expression. L'expression avec le moins de points dans ce test serait la plus spécifique.