Perspective historique
L'article de Wikipedia est assez détaillé sur les origines des expressions régulières (Kleene, 1956). La syntaxe originale était relativement simple avec seulement *
, +
, ?
, |
et le regroupement (...)
. C'était concis ( et lisibles, les deux ne sont pas nécessairement opposés), car les langages formels ont tendance à être exprimés avec des notations mathématiques concises.
Plus tard, la syntaxe et les capacités ont évolué avec les éditeurs et grandi avec Perl , qui essayait d’être concis par nature ( "les constructions courantes devraient être courtes" ). Cela a beaucoup complexifié la syntaxe, mais notez que les gens sont maintenant habitués aux expressions régulières et sont doués pour les écrire (sinon les lire). Le fait qu’ils soient parfois uniquement en écriture suggère que, quand ils sont trop longs, ils ne sont généralement pas le bon outil.
Les expressions régulières ont tendance à être illisibles lorsqu'elles sont maltraitées.
Au-delà des expressions régulières basées sur des chaînes
En ce qui concerne les syntaxes alternatives, examinons celle qui existe déjà ( cl-ppcre , dans Common Lisp ). Votre longue expression régulière peut être analysée ppcre:parse-string
comme suit:
(let ((*print-case* :downcase)
(*print-right-margin* 50))
(pprint
(ppcre:parse-string "^(?:([A-Za-z]+):)?(\\/{0,3})(0-9.\\-A-Za-z]+)(?::(\\d+))?(?:\\/([^?#]*))?(?:\\?([^#]*))?(?:#(.*))?$")))
... et résultats sous la forme suivante:
(:sequence :start-anchor
(:greedy-repetition 0 1
(:group
(:sequence
(:register
(:greedy-repetition 1 nil
(:char-class (:range #\A #\Z)
(:range #\a #\z))))
#\:)))
(:register (:greedy-repetition 0 3 #\/))
(:register
(:sequence "0-9" :everything "-A-Za-z"
(:greedy-repetition 1 nil #\])))
(:greedy-repetition 0 1
(:group
(:sequence #\:
(:register
(:greedy-repetition 1 nil :digit-class)))))
(:greedy-repetition 0 1
(:group
(:sequence #\/
(:register
(:greedy-repetition 0 nil
(:inverted-char-class #\? #\#))))))
(:greedy-repetition 0 1
(:group
(:sequence #\?
(:register
(:greedy-repetition 0 nil
(:inverted-char-class #\#))))))
(:greedy-repetition 0 1
(:group
(:sequence #\#
(:register
(:greedy-repetition 0 nil :everything)))))
:end-anchor)
Cette syntaxe est plus détaillée et, si vous regardez les commentaires ci-dessous, pas nécessairement plus lisible. Donc, ne supposez pas que, puisque vous avez une syntaxe moins compacte, les choses seront automatiquement plus claires .
Toutefois, si vous commencez à avoir des problèmes avec vos expressions régulières, leur conversion dans ce format peut vous aider à déchiffrer et à déboguer votre code. C'est un avantage par rapport aux formats basés sur des chaînes de caractères, où une erreur d'un seul caractère peut être difficile à repérer.
Le principal avantage de cette syntaxe est de manipuler des expressions régulières en utilisant un format structuré au lieu d'un codage basé sur une chaîne. Cela vous permet de composer et de construire de telles expressions comme n'importe quelle autre structure de données de votre programme. Lorsque j'utilise la syntaxe ci-dessus, c'est généralement parce que je veux construire des expressions à partir de parties plus petites (voir aussi ma réponse à CodeGolf ). Pour votre exemple, nous pouvons écrire 1 :
`(:sequence
:start-anchor
,(protocol)
,(slashes)
,(domain)
,(top-level-domain) ... )
Des expressions régulières basées sur des chaînes peuvent également être composées, à l'aide d'une concaténation de chaînes et / ou d'une interpolation incorporée dans des fonctions d'assistance. Cependant, il y a des limites aux manipulations de chaîne qui ont tendance à encombrer le code (pensez aux problèmes d'imbrication, un peu comme les backticks et les $(...)
bash; les caractères d'échappement peuvent également vous donner des maux de tête).
Notez également que le formulaire ci-dessus autorise les (:regex "string")
formulaires afin que vous puissiez mélanger des notations concises avec des arbres. Tout cela conduit à mon humble avis à une bonne lisibilité et composition. il aborde les trois problèmes exprimés par delnan , indirectement (c'est-à-dire pas dans le langage des expressions régulières).
De conclure
Dans la plupart des cas, la notation abrégée est en fait lisible. Il existe des difficultés lorsqu’il s’agit de notations étendues impliquant des retours en arrière, etc., mais leur utilisation est rarement justifiée. L'utilisation injustifiée d'expressions régulières peut conduire à des expressions illisibles.
Les expressions régulières ne doivent pas nécessairement être codées sous forme de chaînes. Si vous avez une bibliothèque ou un outil qui peut vous aider à construire et composer des expressions régulières, vous éviter beaucoup de bugs potentiels liés aux manipulations de cordes.
Alternativement, les grammaires formelles sont plus lisibles et sont meilleures pour nommer et résumer des sous-expressions. Les terminaux sont généralement exprimés sous forme d'expressions régulières simples.
1. Vous préférerez peut-être créer vos expressions à la lecture, car les expressions régulières ont tendance à être des constantes dans une application. Voir create-scanner
et load-time-value
:
'(:sequence :start-anchor #.(protocol) #.(slashes) ... )