De nombreux programmeurs connaissent la joie de créer une expression régulière rapide, de nos jours souvent avec l'aide d'un service Web, ou plus traditionnellement à l'aide d'une invite interactive, ou peut-être même d'écrire un petit script dont l'expression régulière est en cours de développement et une collection de cas de test. . Dans les deux cas, le processus est itératif et assez rapide: continuez à pirater la chaîne d'aspect cryptique jusqu'à ce qu'elle corresponde et capture ce que vous voulez et rejette ce que vous ne voulez pas.
Pour un cas simple, le résultat pourrait ressembler à ceci, sous la forme d'une expression rationnelle Java:
Pattern re = Pattern.compile(
"^\\s*(?:(?:([\\d]+)\\s*:\\s*)?(?:([\\d]+)\\s*:\\s*))?([\\d]+)(?:\\s*[.,]\\s*([0-9]+))?\\s*$"
);
De nombreux programmeurs savent également qu'il est pénible de devoir modifier une expression régulière ou simplement coder autour d'une expression régulière dans une base de code héritée. Avec un peu d’édition pour le séparer, regexp est toujours très facile à comprendre pour ceux qui sont familiarisés avec les expressions rationnelles, et un vétéran de l’expression rationnelle devrait immédiatement voir ce qu’il fait (réponse à la fin du message, au cas où quelqu'un voudrait l'exercice de le découvrir eux-mêmes).
Cependant, les choses n'ont pas besoin d'être beaucoup plus complexes pour qu'une expression rationnelle devienne vraiment une chose en écriture seule, et même avec une documentation diligente (ce que tout le monde fait bien sûr pour tous les expressions rationnelles complexes qu'ils écrivent ...), la modification des expressions rationnelles devient une tâche ardue. tâche ardue. Cela peut aussi être une tâche très dangereuse si l'expression rationnelle n'est pas testée avec soin (mais tout le monde a bien sûr des tests unitaires complets pour toutes leurs expressions rationnelles complexes, qu'elles soient positives ou négatives ...).
Donc, bref, existe-t-il une solution / alternative d'écriture-lecture pour les expressions régulières sans perdre leur pouvoir? À quoi ressemblerait l'expression rationnelle ci-dessus avec une approche alternative? N'importe quelle langue convient, bien qu'une solution multilingue soit préférable, dans la mesure où les expressions rationnelles sont multilingues.
Et ensuite, ce que fait l’expression rationnelle précédente est la suivante: analyser une chaîne de nombres au format 1:2:3.4
, en capturant chaque nombre, où les espaces sont autorisés et 3
obligatoires.
Réponses:
Un certain nombre de personnes ont mentionné composer à partir de pièces plus petites, mais personne n'a encore donné d'exemple, alors voici le mien:
Pas le plus lisible, mais je sens que c'est plus clair que l'original.
En outre, C # a l'
@
opérateur qui peut être préfixé à une chaîne afin d'indiquer qu'il doit être pris à la lettre (pas de caractères d'échappement), doncnumber
serait@"([\d]+)";
la source
[\\d]+
et[0-9]+
devrait être juste\\d+
(enfin, certains peuvent trouver[0-9]+
plus lisible). Je ne vais pas modifier la question, mais vous voudrez peut-être corriger cette réponse.\d
correspond à tout ce qui est considéré comme un numéro, même dans les autres systèmes de numérotation (chinois, arabe, etc.), alors qu'il[0-9]
ne fait que correspondre aux chiffres standard. J'ai normalisé\\d
, cependant, et en a pris en compte dans leoptionalDecimal
modèle.La clé pour documenter l'expression régulière est de le documenter. Bien trop souvent, les gens jettent dans ce qui semble être du bruit de ligne et s'en tiennent là.
Au sein de perl, l'
/x
opérateur situé à la fin de l'expression régulière supprime les espaces permettant de documenter l'expression régulière.L'expression régulière ci-dessus deviendrait alors:
Oui, cela consomme un peu d'espace blanc vertical, bien que l'on puisse le raccourcir sans sacrifier trop de lisibilité.
En regardant cette expression régulière, on peut voir comment cela fonctionne (et ne fonctionne pas). Dans ce cas, cette expression rationnelle correspondra à la chaîne
1
.Des approches similaires peuvent être prises dans une autre langue. L' option python re.VERBOSE y travaille.
Perl6 (l'exemple ci-dessus s'appliquait à perl5) va plus loin avec le concept de règles qui conduit à des structures encore plus puissantes que le PCRE (il donne accès à d'autres grammaires (sans contexte et sensibles au contexte) que celles qui sont régulières et étendues).
En Java (d'où cet exemple est tiré), on peut utiliser la concaténation de chaînes pour former l'expression régulière.
Certes, cela en crée beaucoup plus
"
dans la chaîne, ce qui peut être source de confusion, peut être plus facilement lu (en particulier avec la coloration syntaxique sur la plupart des IDE) et documenté.La clé est de reconnaître le pouvoir et la nature "écrire une fois" dans laquelle les expressions régulières tombent souvent. L'écriture du code pour éviter ceci de manière défensive afin que l'expression régulière reste claire et compréhensible est la clé. Nous mettons en forme le code Java pour plus de clarté - les expressions régulières ne sont pas différentes lorsque le langage vous en donne la possibilité.
la source
Le mode "verbeux" proposé par certaines langues et bibliothèques est l'une des réponses à ces préoccupations. Dans ce mode, les espaces dans l'expression rationnelle sont supprimés (vous devez donc les utiliser
\s
) et les commentaires sont possibles. Voici un petit exemple en Python qui supporte cela par défaut:Dans toutes les langues, implémenter un traducteur du mode commenté au mode "normal" devrait être une tâche simple. Si vous êtes préoccupé par la lisibilité de vos expressions rationnelles, vous justifieriez probablement cet investissement en temps assez facilement.
la source
Chaque langue qui utilise des expressions rationnelles vous permet de les composer à partir de blocs plus simples pour faciliter la lecture. Si vous utilisez quelque chose de plus compliqué que votre exemple, vous devez absolument tirer parti de cette option. Le problème particulier de Java et de nombreux autres langages est qu’ils ne traitent pas les expressions régulières comme des citoyens "de première classe", mais les obligent à se faufiler dans le langage via des chaînes de caractères. Cela signifie que de nombreux guillemets et barres obliques inverses qui ne font pas vraiment partie de la syntaxe des expressions rationnelles et rendent la lecture difficile, mais cela signifie également que vous ne pouvez pas être beaucoup plus lisible que cela sans définir efficacement votre propre mini-langage et interprète.
Bien entendu, Perl était le meilleur moyen d’intégrer des expressions rationnelles, avec son option d’espace et ses opérateurs citant les regex. Perl 6 étend le concept de construction de regex à partir de parties en grammaires récursives réelles, ce qui est tellement préférable d'utiliser ce n'est vraiment aucune comparaison. La langue a peut-être manqué le bateau de la rapidité, mais son support regex était The Good Stuff (tm).
la source
J'aime utiliser Expresso: http://www.ultrapico.com/Expresso.htm
Cette application gratuite présente les fonctionnalités suivantes que je trouve utiles au fil du temps:
Par exemple, avec l'expression régulière que vous venez de soumettre, cela ressemblerait à ceci:
Bien sûr, faire un essai vaut mille mots pour le décrire. S'il vous plaît noter également que je suis note liée de quelque façon que ce soit avec l'éditeur de cette application.
la source
Pour certaines choses, il pourrait être utile d’utiliser une grammaire telle que BNF. Celles-ci peuvent être beaucoup plus faciles à lire que les expressions régulières. Un outil tel que GoldParser Builder peut ensuite convertir la grammaire en un analyseur syntaxique qui effectue le gros du travail pour vous.
Les grammaires BNF, EBNF, etc. peuvent être beaucoup plus faciles à lire et à créer qu’une expression régulière compliquée. GOLD est un outil pour de telles choses.
Le lien wiki c2 ci-dessous contient une liste d'alternatives possibles pouvant être recherchées sur Google, avec quelques discussions à ce sujet. Il s’agit essentiellement d’un lien "voir aussi" pour compléter les recommandations de mon moteur de grammaire:
Alternatives aux expressions régulières
la source
C'est une vieille question et je n'ai vu aucune mention d' expressions verbales, alors j'ai pensé ajouter cette information ici aussi aux futurs demandeurs. Les expressions verbales ont été spécialement conçues pour rendre les regex humains compréhensibles, sans qu'il soit nécessaire d'apprendre la signification des symboles de regex. Voir l'exemple suivant. Je pense que cela fait mieux que ce que vous demandez.
Cet exemple concerne le javascript, vous pouvez maintenant trouver cette bibliothèque pour de nombreux langages de programmation.
la source
Le moyen le plus simple serait de continuer à utiliser regex mais de construire votre expression en composant des expressions plus simples avec des noms descriptifs, par exemple http://www.martinfowler.com/bliki/ComposedRegex.html (et oui, il s'agit de string concat)
Cependant, vous pouvez également utiliser une bibliothèque de combinateur d'analyseurs, par exemple http://jparsec.codehaus.org/, qui vous donnera un analyseur décent complet et récursif. Là encore, le véritable pouvoir provient de la composition (cette fois-ci de la composition fonctionnelle).
la source
Je pensais qu'il valait la peine de mentionner les expressions de grst de logstash . Grok s'appuie sur l'idée de composer des expressions d'analyse syntaxique longues à partir d'expressions plus courtes. Il permet de tester facilement ces blocs de construction et est livré pré-emballé avec plus de 100 modèles couramment utilisés . Autres que ces modèles, il permet d'utiliser la syntaxe de toutes les expressions régulières.
Le modèle ci-dessus exprimé dans grok est (j'ai testé dans l' application de débogage, mais aurait pu gaffe):
Les parties et les espaces optionnels le rendent un peu plus laid que d'habitude, mais ici et dans d'autres cas, l'utilisation de grok peut rendre la vie beaucoup plus agréable.
la source
En F #, vous avez le module FsVerbalExpressions . Il vous permet de composer des expressions rationnelles à partir d'expressions verbales. Il contient également des expressions rationnelles prédéfinies (comme l'URL).
L'un des exemples de cette syntaxe est le suivant:
Si vous n'êtes pas familier avec la syntaxe F #, groupName est la chaîne "GroupNumber".
Ils créent ensuite une expression verbale (VerbEx) qu’ils construisent en tant que "COD (? <GroupNumber> [0-9] {3}) END". Ils testent ensuite la chaîne "COD123END", où ils obtiennent le groupe de capture nommé "GroupNumber". Cela donne 123.
Honnêtement, je trouve la regex normale beaucoup plus facile à comprendre.
la source
Premièrement, comprenez que le code qui fonctionne simplement est un mauvais code. Un bon code doit également signaler avec précision les erreurs rencontrées.
Par exemple, si vous écrivez une fonction pour transférer de l'argent d'un compte d'utilisateur à un autre utilisateur; vous ne renverriez pas simplement un booléen "travaillé ou échoué" car cela ne donnerait à l'appelant aucune idée de ce qui n'allait pas et ne lui permettait pas d'informer l'utilisateur correctement. Au lieu de cela, vous pourriez avoir un ensemble de codes d'erreur (ou un ensemble d'exceptions): compte de destination introuvable, fonds insuffisant dans le compte source, autorisation refusée, impossible de se connecter à la base de données, charge excessive (nouvelle tentative ultérieure), etc. .
Maintenant, pensez à votre exemple "analyser une chaîne de nombres au format 1: 2: 3.4". La regex ne fait que signaler un "succès / échec" qui ne permet pas de présenter un retour adéquat à l'utilisateur (que ce retour soit un message d'erreur dans un journal ou une interface graphique interactive où les erreurs sont affichées en rouge sous la forme types d'utilisateurs, ou quoi que ce soit d'autre). Quels types d'erreurs ne parvient-il pas à décrire correctement? Mauvais caractère dans le premier chiffre, premier chiffre trop grand, deux-points manquants après le premier chiffre, etc.
Pour convertir "un code défectueux qui fonctionne simplement" en "un bon code générant des erreurs descriptives adéquates", vous devez diviser l'expression rationnelle en plusieurs expressions rationnelles plus petites (en général, des expressions rationnelles si petites qu'il est plus facile de le faire sans regex ).
Rendre le code lisible / maintenable n’est qu’une conséquence accidentelle de la qualité du code.
la source
:
? Imaginez un compilateur qui n'a qu'un seul message d'erreur ("ERROR") qui est trop stupide pour dire à l'utilisateur quel est le problème. Maintenant, imaginez des milliers de sites Web qui sont tout aussi stupides et affichent (par exemple) "Adresse e-mail incorrecte" et rien de plus.