Je ne demande pas où pour apprendre. J'ai trouvé beaucoup de bonnes ressources en ligne, des livres, etc.
Mais comment diable puis-je les aborder. Où est le début, la fin? Quand le processeur d'expression rationnelle avance-t-il sur le texte, quand tient-il son support et essaie-t-il une autre correspondance? etc.
J'ai envie d'essayer de comprendre les hiéroglyphes sur les pyramides égyptiennes.
Je pense que la connaissance de la théorie des automates est essentielle à la compréhension.
Une fois que vous comprenez ce qu'est un automate et comment langages réguliers sont définis, il sera beaucoup plus facile de comprendre expressions régulières .
En ce qui concerne la syntaxe spécifique et les différences entre les différentes implémentations ... Eh bien, certaines choses que vous devez simplement vous rappeler. Il y a aussi aides pour cela.
Modifier
Certains des commentaires ci-dessous ont soulevé des points importants:
N'oubliez pas que les expressions régulières (telles qu'elles sont implémentées dans la plupart des langages de programmation) sont un surensemble d'expressions régulières dans la théorie des automates. Bien qu'un bon fond théorique soit un bon point de départ, il ne vous dira pas tout. (Merci, David Thornley)
De nombreux commentateurs disent qu'il est possible d'apprendre les différentes syntaxes d'expression régulière sans apprendre la base théorique. S'il est vrai que vous pouvez apprendre la syntaxe sans bien comprendre comment cela fonctionne, j'ai eu l'impression que la pleine compréhension est ce qu'était l'OP. La question portait sur la base réelle: quand le processeur avance-t-il? Quand ça s'arrête? Comment décide-t-il que c'est un match? C'est la base, c'est la théorie, et elle est basée sur la théorie des automates. Bien sûr, vous pouvez conduire une voiture sans savoir comment fonctionne le moteur. Mais si on vous demande "comment le gaz le fait-il réellement conduire" - vous devez parler de la façon dont le moteur est construit, ne le faites pas vous?
En pratiquant.
J'ai appris en m'amusant avec le web scraping. Je suis sûr que je n'étais pas seul à faire ça juste pour le plaisir.
Un exemple: Écrivez un code qui récupère les derniers scores de football, de tennis (le sport que vous aimez en fait) de votre site Web de sport préféré. Pour ce faire, écrivez du code pour charger la page, extrayez les partitions avec des expressions régulières et exportez-les vers la console ou vers un fichier texte. Assurez-vous qu'avec l'expression régulière que vous choisissez, vous ne récupérez que les scores, et rien d'autre. Parfois, cela peut être assez difficile :-)
Deuxième exemple: écrivez du code qui récupère l'image de votre webcomic préféré (j'aime Sinfest beaucoup par exemple) et qui le stocke quelque part sur votre disque dur. Utilisez uniquement des expressions régulières pour récupérer la balise "img" et son contenu. Le cas échéant, récupérez également son titre s'il est stocké quelque part.
Je sais que vous ne demandez pas de ressources mais Maîtriser les expressions régulières par Jeffrey E.F. Friedl a été la façon dont j'ai appris comment ils fonctionnent et comment les utiliser. Même après en avoir utilisé beaucoup pour analyser différentes choses, le premier chapitre avait de nouvelles choses pour moi.
Vous voulez comprendre ces fichues expressions rationnelles? Lis ce livre.
Où est le début, la fin? Quand le processeur d'expression rationnelle avance-t-il sur le texte, quand tient-il son support et essaie-t-il une autre correspondance? etc.
Je commencerais par clarifier vos objectifs puis déterminer votre style d'apprentissage.
Ce qui m'a frappé dans votre question, c'est que vous demandez "comment puis-je apprendre les expressions régulières?" et ensuite immédiatement suivre avec la question "comment fonctionne le moteur d'expression régulière en interne?" Vous semblez sous-entendre que ces deux choses ont quelque chose à voir l'une avec l'autre, ce qui est révélateur. Peut-être que vous êtes une personne qui apprend comment quelque chose fonctionne en le démontant ou en le construisant vous-même.
Pour les applications débutantes, il n'est généralement pas nécessaire de comprendre le fonctionnement d'un outil pour l'utiliser efficacement. Vous n'avez pas besoin de savoir comment fonctionne un moteur de forage pour percer des trous dans le bois; vous devez comprendre comment utiliser l'exercice, pas comment construire un exercice.
Alors quel est ton objectif? Avez-vous l'intention d'apprendre à construire un moteur d'expression régulière? ou avez-vous l'intention d'apprendre à utiliser efficacement des expressions régulières pour résoudre des problèmes commerciaux? des objectifs différents nécessitent probablement des techniques d'apprentissage différentes.
Pour répondre à votre question spécifique sur le fonctionnement du moteur d'expression régulière: cela dépend. L'approche théorique "classique" des expressions régulières consiste à utiliser l'expression régulière comme modèle pour un automate fini non déterministe, puis à construire l'automate fini déterministe équivalent, puis à exécuter cet automate contre l'entrée.
Presque personne ne fait cela pour plusieurs raisons. Tout d'abord, le nombre d'états multiplié par le nombre de caractères d'entrée possibles produit une table de transition d'état qui est énorme, même pour les petites expressions régulières. Bien sûr, la plupart de ces données peuvent être compressées, mais tout de même, c'est beaucoup de règles de transition. Deuxièmement, d'autres approches sont généralement plus rapides. Troisièmement, les expressions dites "régulières" se trouvent dans les bibliothèques d'expression rationnelle modernes, rien de tout cela. Ce ne sont pas des langues régulières; ils sont souvent reconnus par les automates pushdown, et non par les langages d'automates finis.
(J'ai commencé à écrire une longue série sur le fonctionnement de tout cela, mais j'ai manqué de Steam après seulement le douze premiers articles . Vous pourriez les trouver intéressants si vous souhaitez une brève introduction sur le contexte théorique de expressions régulières de base.)
Les vrais moteurs d'expression régulière utilisent généralement une stratégie de retour en arrière. Le moteur d'expression régulière que nous avons construit pour le moteur JScript il y a plus de dix ans compile maintenant l'expression régulière dans un langage de bytecode qui inclut des primitives pour reconnaître les séquences et revenir en arrière aux états antérieurs. Nous avons ensuite construit un interpréteur pour ce langage de bytecode.
Je n'essaierais pas de comprendre comment fonctionne un moteur d'expression rationnelle avant d'avoir une compréhension assez solide de la façon de utiliser les expressions régulières. Concentrez-vous sur cela avant de commencer à creuser dans les stratégies d'optimisation des différents moteurs.
Comment diable puis-je les aborder?
Comme toute nouvelle chose:
10 Study
20 Practice
30 goto 10
Je trouve que la plupart des enseignants qui réussissent commencent à enseigner n'importe quelle matière en fournissant d'abord un peu de contexte à la matière. Il est important d'avoir un contexte de ce que vous apprenez et, surtout, pourquoi vous l'apprenez.
Les expressions régulières sont un moyen de faire correspondre les modèles dans le texte. C'est un langage déclaratif lui-même incorporé dans de nombreux autres langages de programmation.
Je voudrais souligner que c'est un langage déclaratif, les expressions régulières sont utiles pour exprimer la chaîne quoi à faire correspondre, mais elles n'expriment en aucune façon comment le programme consiste à faire l'appariement. Pour cette raison, il est possible d'utiliser des expressions régulières très rapidement et très lentement dans le même langage de programmation simplement en utilisant un analyseur RegEx différent.
La raison de la création d'expressions régulières est la même pour la création de la plupart des langages de programmation: les programmeurs se sont retrouvés à effectuer la même tâche compliquée encore et encore et ont décidé qu'ils voulaient un moyen plus simple d'écrire le code.
Certains vont (et devraient) se plaindre de ma phrase précédente en disant quelque chose comme:
c'est vrai
RegEx ne simplifie pas un programme, RegEx simplifie l'écriture du programme plus simple. Vous devez toujours être minutieux dans vos tests pour vous assurer que tous les cas corrects correspondent correctement et que tous les cas incorrects ne le sont pas. Il est vraiment difficile de tester "tous", et avec des motifs compliqués, il est vraiment difficile de tester "la plupart". Au pire, vous devriez toujours tester "certains" cas.
permet d'incorporer quelques exemples J'ai obligatoirement choisi le moteur RegEx de JavaScript parce que je peux le tester facilement dans le navigateur et parce que je n'aurai pas à échapper de chaîne lors de l'utilisation des littéraux RegEx.
Lorsque vous effectuez une correspondance de chaîne normale, vous testez une valeur de chaîne par rapport à une autre. Ils peuvent venir de n'importe où, mais au final, il faut comparer deux chaînes l'une à l'autre:
if ( 'foo' == 'bar' ) doSomething();
Cet exemple est nul car il ne sera jamais faire quoi que ce soit
if ( foo == 'bar' ) doSomething();
Beaucoup mieux; maintenant, nous ne savons pas à l'avance si quelque chose sera fait ou non. Nous pouvons maintenant commencer à accepter les entrées des utilisateurs:
if ( Prompt( 'Say "bar" to do something.' ) == 'bar' ) doSomething();
Merveilleux, les utilisateurs peuvent désormais saisir bar
et quelque chose se produira jusqu'à ce que vous obteniez des rapports de bogue des utilisateurs disant que "bar"
ne fonctionne pas, ou que "BAR" ne fonctionne pas, ou qu'ils ont tapé BRA
100 fois et que rien ne se produit.
Ignorant les fautes d'orthographe et les caractères supplémentaires, 'bar' != 'BAR'
, et les programmeurs doivent trouver un moyen de tester où les caractères sont dans le mauvais cas.
Solution simple, utilisez toLowerCase
. Cela fonctionne à merveille, mais qu'en est-il de nos utilisateurs qui utilisent l'anglais britannique sur l'anglais américain lorsque vous correspondez something == 'color'
? Vous devez maintenant faire correspondre something == 'color' || somthing == 'colour'
.
Pour faire court, les schémas simples se transforment en beaucoup de code répétitif très rapidement.
L'exemple de couleur peut simplement être associé à:
/colou?r/.test( something )
une solide compréhension des principes de base des expressions régulières peut réduire considérablement le temps que vous perdez à réinventer la roue.
La plupart des langues qui implémentent des expressions régulières ont au moins une ressource disponible pour la syntaxe spécifique de l'utilisation des expressions régulières dans cette langue. Un pour JavaScript peut être trouvé sur MDN
lisez-le.
tout.
puis relisez-le.
Il faut du temps pour apprendre, pensez-y comme un investissement: une heure pour apprendre RegEx économise maintenant une heure la prochaine fois que vous devez effectuer une correspondance de modèle de chaîne, puis une autre heure la prochaine fois par la suite.
Après avoir lu tout sur RegEx, vous n'en comprendrez probablement pas la plupart. C'est parce que vous n'êtes en fait pas en train de faire quoi que ce soit avec.
J'ai mentionné pourquoi j'ai choisi JS pour cet exemple, je vous invite à jouer avec dans votre navigateur. C'est rapide, et vous pouvez le faire directement dans votre barre d'URL.
JS a quelques façons différentes et simples d'utiliser RegEx:
string.match( regex )
regex.exec( string )
regex.test( string )
Commençant par quelque chose de simple comme:
javascript:'color'.match(/colou?r/);
est un moyen facile de mettre le pied dans la porte. Jouez avec lui, cassez-le pour voir ce qui correspond et ce qui ne correspond pas.
Lorsque vous êtes bloqué sur la pratique, continuez à 30
. Vous devez lire pour en savoir plus, mais vous devez vous entraîner pour vraiment comprendre ce que vous avez appris.
Brian Kernighan écrit un simple processeur reg-ex dans le livre Beautiful Code . Je me rends compte que vous ne cherchez pas de ressources, mais cela pourrait aider à voir une implémentation de base , à l'intérieur.
En développement normal, le débogage du code peut fournir des informations très utiles. Les expressions régulières ne sont pas différentes. Donc, au risque de ressembler à une publicité, obtenez RegexBuddy . Il a un excellent outil pour afficher visuellement ce que fait le moteur car il gère votre expression et la chaîne d'entrée.
En plus d'une bonne référence, la façon dont vous apprenez vraiment est d'utiliser de bons outils d'apprentissage. L'un utilise l'éditeur open-source Vim , avec deux options définies:
L'autre consiste à utiliser un appel d'outil gratuit RegExCoach . Vous collez le texte que vous souhaitez rechercher, puis dans une autre fenêtre vous développez votre expression régulière. Comme Vim, il met en évidence les matchs réussis à la volée.
Je vais vous donner une réponse simple pour une question simple. Tout d'abord, vous devez comprendre ce que sont les expressions régulières (RegEx) - ce qu'elles font, à quoi elles servent. Ensuite, un excellent outil pour commencer.
Qu'Est-ce que c'est? RegEx est un langage pour exprimer la correspondance de motifs. C'est-à-dire qu'en l'utilisant, vous pouvez créer une combinaison de caractères qui reconnaît ou trouve des motifs dans le texte. Comment est-ce utile? Lors de la programmation, vous pouvez indiquer aux ordinateurs de faire correspondre le texte d'une certaine source (une entrée utilisateur, une page Web, etc.) et détecter si des éléments de texte spécifiques y sont contenus. Par exemple, un point (.) Représente n'importe quel caractère - lettre ou chiffre. Les nombres entre accolades représentent le nombre d'itérations, donc ". {1,30}" indique n'importe quel caractère, répété entre 1 et 30 fois - en d'autres termes, vous ne pouvez pas avoir une chaîne vide, et elle ne peut pas dépasser 30 personnages. Et ça continue à partir de là.
Comment commencer à apprendre? Le meilleur outil absolu que j'ai vu est Expresso , mais ce n'est que pour Windows. Il a une interface graphique très étendue où vous cliquez sur les éléments que vous souhaitez ajouter à votre expression, puis un testeur pour le comparer à diverses entrées pour voir les résultats. Je n'ai rien vu de bon sur le Mac (mais j'utilise Windows sur VMWare, donc je n'ai pas vraiment besoin d'une version Mac), je n'ai pas passé beaucoup de temps à chercher sur Linux.
Les expressions régulières peuvent devenir très compliquées très rapidement, donc je vous recommande de commencer à l'apprendre en utilisant des tutoriels. Sachez que la forme d'expression régulière la plus simple est une chaîne représentant ce que vous recherchez. Malheureusement, pour pouvoir définir des règles de recherche spéciales, il faut certains caractères, et ces caractères doivent être échappés sinon vous créeriez une expression régulière invalide ou incorrecte.
Mon conseil est de commencer par un exemple de quelque chose que vous recherchez et d'y échapper. En d'autres termes, si vous recherchez quelque chose entre parenthèses, prenez un exemple d'une telle chaîne dans le texte que vous recherchez: (this is an example of something you'd want to find)
Commencez par échapper les caractères afin de rechercher le caractère littéral: \(this is an example of something you'd want to find\)
Testez-le, vérifiez qu'il trouve correctement votre exemple. Généralisez ensuite l'expression pour trouver un tel texte, pas seulement l'exemple que vous avez trouvé. Il deviendrait alors: \([^)]*\)
(signifie tout caractère qui n'est pas ")" pour un nombre quelconque d'occurrences, y compris 0).
Testez-le à nouveau et vérifiez que non seulement il trouve votre exemple, mais que d'autres l'aiment. Recherchez des expressions régulières plus compliquées mais plus fréquentes sur Internet et corrigez-les avec vos expressions régulières existantes pour éviter d'avoir à vous soucier de chaque possibilité.
C'est à peu près ça. Et oh, apprends et aime\Q ...\E. Dans la plupart des langages d'expressions régulières,\Q indique le début d'un modèle littéral et\E marque la fin, au cas où vous devriez vous occuper de rechercher des modèles particulièrement sophistiqués et ne savez pas comment y échapper. Cela m'a sauvé la vie plus d'une ou deux fois.
Deux bonnes autres réponses vous disent d'apprendre la théorie derrière les regex et de pratiquer, qui sont tous deux d'excellents conseils. Je recommanderais également d'obtenir un bon outil d'expression rationnelle visuelle pour vous aider si vous êtes sérieux.
RegexBuddy , par exemple, dispose d'un mode de débogage visuel qui vous permet de parcourir l'exécution d'une regex, et vous montre via des surbrillances et un texte explicatif ce qu'est le moteur regex faire à chaque étape. Il y a une vidéo démontrant ce débogage sur leur site.
Tout ce que nous pouvons vous donner, c'est plus de ressources à apprendre. Cette question est elle-même une ressource.
Au fait, j'ai appris assez facilement les expressions régulières sur ce site: http://www.regular-expressions.info/
Vous commencez avec une comparaison de chaînes de base. Très facile, mais pas aussi puissant.
Ensuite, il vous est peut-être venu à l'esprit que vous avez besoin de comparaisons insensibles à la casse, de sorte que "grec" et "grec" se comparent de manière égale. C'est un peu plus puissant.
Un jour, vous remarquerez que de petites différences d'orthographe ne devraient pas empêcher 2 mots de comparer égaux: c'est-à-dire que "organiser" et "organiser" devraient comparer égaux. Vous vous asseyez et écrivez du code qui fait cela et vous êtes heureux.
Jusqu'à ce que vous absteniez un peu plus et réalisiez que vous voulez parfois que tous les mots qui se terminent par "ize" soient comparables à leurs frères en orthographe britannique. Ou, des répétitions de certaines chaînes un certain nombre de fois. Et, bien sûr, vous devez combiner tout cela.
Etc. Enfin, vous vous retrouvez très probablement avec une notation où tous les caractères ne se représentent pas. Rien d'autre n'est une expression rationnelle. On peut le voir comme la description d'un ensemble de chaînes.
Et puis, c'est assez facile et se résume aux 3 principes de base suivants:
Vous avez des expressions rationnelles de base: caractères qui se tiennent pour eux-mêmes, classes de caractères, abréviations pratiques et pas si pratiques pour les classes de caractères comme\d ou\p {Lu} pour les lettres majuscules.
Et puis, vous avez quelques possibilités pour les combiner: si r1 et r2 sont des regexps, alors r1r2 r1 | r2 (r1) le sont aussi.
Dernier point, mais non le moindre, les modificateurs de répétition: r? r * r + r {n, m}
C'est tout ce que vous devez savoir. Tout ce que vous pouvez rechercher lorsque vous en avez besoin.
Pour moi, voir à quoi correspond l'expression rationnelle au fur et à mesure que je le construis me facilite vraiment la vie et m'a aidé à mieux les comprendre.
Pour ce faire, je vais ouvrir un fichier avec le texte cible dans Emacs, puis utiliser le isearch-forward-regexp
commande. Lorsque vous entrez l'expression rationnelle, Emacs vous montre à quoi il correspond (c'est la partie "isearch").
Pour exécuter la commande, dans Emacs, vous pouvez utiliser <ESC>xisearch-forward-regexp
.
J'ai appris les expressions régulières en apprenant le flex et le bison, qui sont utilisés pour construire des analyseurs et des analyseurs lexicaux. Vous ne pourriez pas avoir un analyseur sans expressions régulières, et le livre lexx et yacc est incroyablement bon pour parcourir la théorie sans aller trop vite.
Fondamentalement, pratiquement tous les moteurs regex suivent de nos jours les mêmes principes. Ils sont tous machines à états finis et si vous le croyez vraiment, alors vous avez une longueur d'avance sur presque n'importe quel code que vous écrivez. Cela ressemble à l'apprentissage de la récursivité en ce sens qu'une fois que vous l'avez obtenu, vous l'appliquez instinctivement à des problèmes. Ils sont faciles à résoudre avec le bon outil, mais très difficiles sans lui.
Une autre chose à propos de l'apprentissage de lexx et yacc, par rapport aux expressions régulières, est que vous apprenez comment elles fonctionnent en interne. Comment le programme regarde-t-il vers l'avant, pourquoi il termine un match, comment il conserve les données, et bien plus encore. Comprendre les pointeurs est un must absolu, mais si vous obtenez lexx et yacc, et que vous le parcourez depuis le début, vous apprendrez tout ce que vous avez demandé et disposerez d'un outil extrêmement puissant pour le reste de votre carrière.
Cette question comprend un tas de ressources pour l'apprentissage, et un squelette flexible que j'ai jeté ensemble.
De plus, j'essaie d'abord de m'assurer qu'il n'y a pas de moyen plus simple de résoudre le problème/de "tokeniser" la chaîne.
Quand vous ne pouvez pas en trouver un, je le considère comme un problème non pas d'essayer de faire correspondre ce que vous voulez sortir de la chaîne, mais plutôt de ne PAS faire correspondre ce que vous ne voulez pas. C'est principalement parce que les regex sont gourmandes. Mais cela m'a bien servi d'approche pour obtenir ce que je veux.
Voici un exemple:
string = "Sep 22 19:57:38 Host fcron[9137]: \
Job fbsetbg -r $HOME/backgrounds/ \
started for user user (pid 9138)"
pour correspondre à la minute:
string.match /^\w+\s\d+\s\d+:(\d+):\d+\s\w+\s/ # correct but bad
string.match /\d+:([^:]+):\d+/ # correct and good
Au lieu d'essayer de trouver l'heure avec tout le reste, essayez de trouver les limites distinctes.
L'exemple est un peu artificiel, mais tout ce que j'ai pu trouver.
Une approche que j'ai utilisée était de trouver un tas de projets open source qui nécessitaient des mises à jour de syntaxe, puis d'écrire un script sed de plus en plus complexe, qui comprenait de nombreuses expressions régulières.
Le script devait s'exécuter sur de nombreux fichiers différents dans chaque projet open source. Ensuite, exécutez-vous contre de nombreux projets différents avec des styles différents. J'ai commencé avec quelque chose de très simple comme %s/before/after
alors j'ai trouvé qu'il correspondait à trop de cas. j'ai donc ajouté plus de choses pour éviter cela. Ensuite, j'ai trouvé différents projets utilisant différents styles de syntaxe qui nécessitaient des modifications différentes.
En fin de compte, je me suis retrouvé avec
et a été aidé dans cette approche par la nécessité de
Je transmettrai également qu'il existe un tas de sites pour les différentes langues - Ruby, javascript, etc. qui vous permettront de jouer avec des expressions et des exemples de texte pour une gratification immédiate. Ceux-ci sont:
expressions régulières en plusieurs langues sur un seul site
se concentrer sur les groupes de match:
J'ai trouvé l'apprentissage d'expressions régulières similaire à l'apprentissage des tables de multiplication - oui, vous devez comprendre les idées qui le sous-tendent, mais en fin de compte, vous n'avez qu'à le faire souvent et à plusieurs reprises.
Quand j'apprenais, je me fixais comme objectif de faire quelques exercices d'expression régulière par jour. En pratique, cela signifiait au moins une fois par jour, j'essayais de regarder une chaîne ou un texte sur mon écran, et je relevais un défi - "puis-je obtenir toutes les adresses e-mail d'ici", ou "trouver toutes les occurrences du mot "code" utilisé comme verbe plutôt que comme nom, "des trucs comme ça.
Faire cela pendant quelques semaines a vraiment payé - et bien sûr, des révisions périodiques et des rafraîchissements sont nécessaires. Je suis sur le point d'en avoir un.
J'ai également trouvé cet outil en ligne utile, car il me permet de tester l'expression régulière en temps réel: http://www.gethifi.com/tools/regex