Quand ne PAS utiliser les expressions régulières? [fermé]

50

Les expressions régulières sont un outil puissant dans l'arsenal du programmeur, mais il existe des cas où elles ne constituent pas le meilleur choix, voire qu'elles sont totalement nuisibles.

L'exemple simple n ° 1 consiste à analyser HTML avec regexp - une route connue pour de nombreux bogues. Cela est probablement dû également à l' analyse en général.

Mais, y a-t-il d'autres zones clairement interdites pour les expressions régulières?


ps: " La question que vous posez a un caractère subjectif et est susceptible d'être fermée. "

c69
la source
9
L'analyse HTML avec regexp n'est pas simplement "une route connue pour de nombreux bugs". C'est en fait impossible .
Kramii Réintègre Monica
19
Non seulement c'est impossible, mais cela mène également à la folie et à la damnation éternelle
Martin Wickman Le
3
@ Jörg: Regexp est juste une abréviation pour expression régulière.
Joren
3
@ Jörg: Il est tout à fait vrai qu'il existe une différence énorme entre les expressions régulières en mathématiques et leur implémentation dans des bibliothèques de logiciels. Il est également vrai que la plupart des bibliothèques d'expressions régulières ont des extensions qui les placent bien au-delà de la simple acceptation de langages normaux, et que les appeler des expressions régulières n'est pas toujours approprié. Je suis d'accord avec vous qu'il y a deux concepts différents. Mais ils ont le même nom; l'expression rationnelle n'est toujours qu'une abréviation, pas un terme en soi. Beaucoup d’exemples sur ce site utilisent le terme complet pour désigner les bibliothèques de logiciels.
Joren
2
@ Jörg - ce sont des sémantiques. Bien que cela puisse être une bonne idée d’appeler ces motifs sous des noms différents (ne serait-ce que pour éviter les "erreurs des expressions rationnelles pour les langages normaux"), "regexp" / "expressions régulières" n’est pas une très bonne tentative et ne conduit qu'à confusion supplémentaire.
Kobi

Réponses:

60

N'utilisez pas d'expressions régulières:

  • Quand il y a des parseurs.

Cela ne se limite pas à HTML . Un simple XML valide ne peut pas être raisonnablement analysé avec une expression régulière, même si vous connaissez le schéma et savez qu'il ne changera jamais.

N'essayez pas, par exemple, d' analyser le code source C # . Au lieu de cela, analysez-le pour obtenir une arborescence significative ou les jetons.

  • Plus généralement, lorsque vous avez de meilleurs outils pour faire votre travail.

Que faire si vous devez rechercher une lettre, petite ou capitale? Si vous aimez les expressions régulières, vous les utiliserez. Mais n'est-il pas plus facile / plus rapide / lisible d'utiliser deux recherches l'une après l'autre? Il est probable que dans la plupart des langues, vous obtiendrez de meilleures performances et que votre code soit plus lisible.

Par exemple, l'exemple de code dans la réponse d'Ingo est un bon exemple dans lequel vous ne devez pas utiliser d'expressions régulières. Il suffit de chercher foo, puis de bar.

  • Lors de l'analyse de l'écriture humaine.

Un bon exemple est un filtre d'obscénité. Non seulement c'est une mauvaise idée de l'implémenter en général, mais vous pouvez être tenté de le faire en utilisant des expressions régulières et vous le ferez mal. Un humain peut écrire un mot, un nombre, une phrase de différentes manières et sera compris par un autre humain, mais pas par votre expression habituelle. Ainsi, au lieu d’attraper une véritable obscénité, votre expression habituelle passera son temps à faire mal aux autres utilisateurs.

  • Lors de la validation de certains types de données.

Par exemple, ne validez pas une adresse électronique à l'aide d'une expression régulière. Dans la plupart des cas, vous le ferez mal. Dans de rares cas, vous le ferez bien et vous terminerez avec une horreur de 6 343 caractères .

Sans les bons outils, vous ferez des erreurs. Et vous les remarquerez au dernier moment, ou peut-être jamais. Si vous ne vous souciez pas du code propre, vous écrirez une chaîne de vingt lignes sans commentaires, sans espaces, sans nouvelles lignes.

  • Quand votre code sera lu. Et ensuite, relisez, et encore et encore, à chaque fois par différents développeurs.

Sérieusement, si je prends votre code et que je dois le réviser ou le modifier, je ne veux pas passer une semaine à essayer de comprendre une chaîne de vingt lignes contenant beaucoup de symboles.

Arseni Mourzenko
la source
9
"Sérieusement, si je prends votre code et que je dois le réviser ou le modifier, je ne veux pas passer une semaine à essayer de comprendre une chaîne de vingt lignes contenant beaucoup de symboles." +1!
Funkybro
1
C'est une bien meilleure réponse que son demi-frère sur le débordement de pile: stackoverflow.com/questions/7553722/…
Kobi
1
Si vous utilisez Perl / PCRE (et probablement les autres versions de regex modernes), renseignez-vous sur les sous-routines, les groupes de capture nommés et les (?(DEFINE))assertions;) Vous pouvez écrire des regex très propres à l'aide de ceux-ci. très similaire à ce que vous
écririez
2
L'utilisation d'expressions régulières pour éliminer les mots de la liste noire est une erreur classique.
Dan Ray
Il n’ya aucune raison au monde d’éviter de lancer une expression régulière sur une chaîne comme "<a href='foo'>stuff</a>". Les expressions rationnelles modernes n'ont aucun problème avec cela.
Tchrist
18

Le plus important: lorsque le langage que vous analysez n’est pas un langage courant .

Le langage HTML n’est pas un langage courant et il n’est pas possible de l’ analyser avec une expression régulière (ce n’est pas seulement difficile ou c’est une route menant au code buggy).

Matteo
la source
4
Faux! Si vous utilisez l’une des variantes de regex les plus modernes (Perl, PCRE, Java, .NET, ...), vous pouvez effectuer des récursions et des assertions et ainsi analyser également des grammaires dépourvues de contexte.
NikiC
9
@NikiC. Pas faux. Les "saveurs de regex modernes" ne sont pas des expressions régulières (qui peuvent être utilisées pour analyser des langages normaux, d'où son nom). Je conviens qu'avec PRE, vous pouvez faire plus, mais je ne les appellerais pas simplement des "expressions régulières" (comme dans la question initiale).
Matteo
1
Les regex modernes vont bien au-delà de ce que votre grand-mère a appris: les regex pourraient le faire si ses conseils sont sans importance. Et même les expressions rationnelles primitives peuvent gérer la plupart des extraits de code HTML. Cette interdiction générale est ridicule et irréaliste. Les regexes ont été faites pour ce genre de chose. Et oui, je sais de quoi je parle .
Tchrist
12

Sur stackoverflow, on voit souvent des personnes demander des expressions rationnelles qui déterminent si une chaîne donnée ne contient pas ceci ou cela. C'est, à mon humble avis, inverser le but de l'expression régulière. Même s'il existe une solution (en utilisant des assertions de regard négatives derrière soi ou ce genre de choses), il est souvent préférable d'utiliser l'expression régulière pour son but et de gérer le cas négatif avec la logique de programme.

Exemple:

# bad
if (/complicated regex that assures the string does NOT conatin foo|bar/) {
    # do something
}

# appropriate
if (/foo|bar/) {
    # error handling
} else {
    # do something
}
Ingo
la source
1
+1: Quelques fois, j'ai évité de me prendre dans un coin avec des regex en m'arrêtant et en me demandant "d'accord, qu'est-ce que j'essaye spécifiquement de faire correspondre?" plutôt que "Qu'est-ce que j'essaie d'éviter?"
5

Deux cas:

Quand il y a un moyen plus facile

  • La plupart des langages fournissent une fonction simple comme INSTR pour déterminer si une chaîne est un sous-ensemble d'une autre. Si c'est ce que vous voulez faire, utilisez la fonction la plus simple. N'écris pas ta propre expression régulière.

  • Si une bibliothèque est disponible pour effectuer une manipulation de chaîne complexe, utilisez-la plutôt que d'écrire votre propre expression régulière.

Lorsque les expressions régulières ne sont pas suffisamment puissantes

  • Si vous avez besoin d'un analyseur, utilisez un analyseur.
Kramii réintègre Monica
la source
0

Les expressions régulières ne peuvent pas identifier les structures récursives . C'est la limitation fondamentale.

Prenez JSON - c'est un format assez simple, mais comme un objet peut contenir d'autres objets en tant que valeurs membres (arbitrairement profondes), la syntaxe est récursive et ne peut pas être analysée par une expression régulière. D'autre part, CSV peut être analysé par regex'es puisqu'il ne contient aucune structure récursive.

En bref, les expressions régulières ne permettent pas au motif de se référer à lui-même. Vous ne pouvez pas dire: à ce stade de la syntaxe, associez à nouveau l'ensemble du modèle. En d'autres termes, les expressions régulières ne correspondent que de manière linéaire, elle ne contient pas de pile qui lui permettrait de garder une trace de la profondeur à laquelle se trouve un modèle imbriqué.

Notez que cela n’a rien à voir avec la complexité ou la complexité du format. Les expressions S sont vraiment très simples, mais ne peuvent pas être analysées avec une expression régulière. CSS2, en revanche, est un langage assez complexe, mais ne contient pas de structures récursives et peut donc être analysé avec une expression régulière. (Bien que cela ne soit pas vrai pour CSS3 en raison des expressions CSS, qui ont une syntaxe récursive.)

Ce n’est donc pas parce qu’il est laid, complexe ou sujet aux erreurs d’analyser HTML en utilisant uniquement regex. C'est que ce n'est tout simplement pas possible .

Si vous devez analyser un format contenant des structures récursives, vous devez au moins compléter l'utilisation d'expressions régulières avec une pile pour garder une trace du niveau des structures récursives. C'est typiquement comment un analyseur fonctionne. Les expressions régulières sont utilisées pour reconnaître les parties "linéaires", tandis que le code personnalisé en dehors de l'expression rationnelle est utilisé pour suivre les structures imbriquées.

Généralement, l'analyse de ce type est divisée en phases distinctes. La tokénisation est la première phase où les expressions régulières sont utilisées pour scinder l'entrée en une séquence de "jetons" tels que des mots, des signes de ponctuation, des crochets, etc. L'analyse est la phase suivante où ces jetons sont analysés dans une structure hiérarchique, un arbre de syntaxe.

Ainsi, lorsque vous entendrez que HTML ou C # ne peuvent pas être analysés par des expressions rationnelles, sachez que celles-ci font toujours partie intégrante des analyseurs. Vous ne pouvez pas analyser un tel langage en utilisant uniquement des expressions régulières et aucun code d'assistance.

JacquesB
la source