Expressions régulières regex. Expressions régulières pour les débutants

Modificateurs

Le symbole moins (-) placé à côté d'un modificateur (sauf U) crée sa négation.

Caractères spéciaux

AnalogueDescription
() sous-modèle, expression imbriquée
caractère générique
(une,b) nombre d'occurrences de "a" à "b"
| "ou" logique, dans le cas d'alternatives à un seul caractère, utilisez
\ échapper au caractère spécial
. n'importe quel caractère sauf le saut de ligne
\d chiffre décimal
\D[^\d]tout caractère autre qu'un chiffre décimal
\f fin (saut de page)
\n saut de ligne
\pL lettre en codage UTF-8 lors de l'utilisation du modificateur u
\r retour chariot
\s[\t\v\r\n\f]caractère spatial
\S[^\s]n'importe quel symbole sauf celui qui clignote
\t tabulation
\w n'importe quel chiffre, lettre ou trait de soulignement
\W[^\w]tout caractère autre qu'un chiffre, une lettre ou un trait de soulignement
\v onglet vertical

Caractères spéciaux dans une classe de caractères

Position dans une ligne

ExempleCorrespondanceDescription
^ ^unun aa aaadébut de ligne
$ un $aaa aa un fin de ligne
\UN\Aaun aa aaa
aaa aaa
début du texte
\za\zaaa aaa
aaa aa un
fin du texte
\bune\b
\ba
aa un aa un
un aa un aa
limite de mot, déclaration : le caractère précédent est verbal, mais le suivant ne l'est pas, ou vice versa
\B\Ba\Bun un un un un unpas de limite de mots
\G\Géorgieaaa aaaRecherche précédente réussie, la recherche s'est arrêtée à la 4ème position - où a n'a pas été trouvé
Télécharger en PDF, PNG.

Ancres

Les ancres dans les expressions régulières indiquent le début ou la fin de quelque chose. Par exemple, des lignes ou des mots. Ils sont représentés par certains symboles. Par exemple, un modèle correspondant à une chaîne commençant par un nombre ressemblerait à ceci :

Ici, le caractère ^ désigne le début de la ligne. Sans cela, le modèle correspondrait à n'importe quelle chaîne contenant un chiffre.

Classes de personnages

Les classes de caractères dans les expressions régulières correspondent à un certain ensemble de caractères à la fois. Par exemple, \d correspond à n'importe quel nombre de 0 à 9 inclus, \w correspond à des lettres et des chiffres et \W correspond à tous les caractères autres que les lettres et les chiffres. Le motif identifiant les lettres, les chiffres et l'espace ressemble à ceci :

POIX

POSIX est un ajout relativement nouveau à la famille des expressions régulières. L'idée, comme pour les classes de caractères, est d'utiliser des raccourcis qui représentent un groupe de caractères.

Déclarations

Presque tout le monde a du mal à comprendre les affirmations au début, mais à mesure que vous vous familiariserez avec elles, vous vous retrouverez à les utiliser assez souvent. Les assertions permettent de dire : « Je souhaite trouver tous les mots de ce document qui incluent la lettre « q » et qui ne sont pas suivis de « werty ».

[^\s]*q(?!werty)[^\s]*

Le code ci-dessus commence par rechercher des caractères autres que l'espace ([^\s]*) suivi de q . L’analyseur parvient alors à une assertion prospective. Cela rend automatiquement l'élément précédent (caractère, groupe ou classe de caractères) conditionnel : il ne correspondra au modèle que si l'instruction est vraie. Dans notre cas, l'énoncé est négatif (?!), c'est-à-dire qu'il sera vrai si ce qu'on y cherche n'est pas trouvé.

Ainsi, l'analyseur vérifie les caractères suivants par rapport au modèle proposé (werty). S'ils sont trouvés, alors la déclaration est fausse, ce qui signifie que le caractère q sera « ignoré », c'est-à-dire qu'il ne correspondra pas au modèle. Si werty n’est pas trouvé, alors la déclaration est vraie et tout est en ordre avec q. Ensuite, la recherche continue pour tous les caractères autres que l'espace ([^\s]*).

Quantificateurs

Les quantificateurs permettent de définir une partie d'un motif qui doit être répétée plusieurs fois de suite. Par exemple, si vous souhaitez savoir si un document contient une chaîne de 10 à 20 lettres (incluses) « a », alors vous pouvez utiliser ce modèle :

UNE(10,20)

Par défaut, les quantificateurs sont « gourmands ». Ainsi, le quantificateur +, signifiant « une ou plusieurs fois », correspondra à la valeur maximale possible. Parfois, cela pose des problèmes, auquel cas vous pouvez dire au quantificateur de cesser d'être gourmand (devenir « paresseux ») en utilisant un modificateur spécial. Regardez ce code :

".*"

Ce modèle correspond au texte placé entre guillemets doubles. Cependant, votre ligne source pourrait ressembler à ceci :

Bonjour le monde

Le modèle ci-dessus trouvera la sous-chaîne suivante dans cette ligne :

"helloworld.htm" title="(!LANG : Bonjour tout le monde" !}

Il s'est avéré trop gourmand, saisissant le plus gros morceau de texte possible.

".*?"

Ce modèle correspond également à tous les caractères placés entre guillemets doubles. Mais la version paresseuse (remarquez le modificateur ?) recherche la plus petite occurrence possible, et trouvera donc chaque sous-chaîne entre guillemets individuellement :

"bonjour le monde.htm" "Bonjour le monde"

S'échapper dans les expressions régulières

Les expressions régulières utilisent certains caractères pour représenter différentes parties d'un modèle. Cependant, un problème se pose si vous devez rechercher l'un de ces caractères dans une chaîne, tout comme un caractère normal. Un point, par exemple, dans une expression régulière signifie « tout caractère autre qu'un saut de ligne ». Si vous avez besoin de trouver un point dans une chaîne, vous ne pouvez pas simplement utiliser " . » comme modèle - cela permettra de trouver presque n'importe quoi. Vous devez donc indiquer à l'analyseur que ce point doit être considéré comme un point normal et non comme "n'importe quel caractère". Cela se fait à l'aide d'un signe d'échappement.

Un caractère d'échappement précédant un caractère tel qu'un point amène l'analyseur à ignorer sa fonction et à le traiter comme un caractère normal. Plusieurs caractères nécessitent un tel échappement dans la plupart des modèles et des langues. Vous pouvez les trouver dans le coin inférieur droit de l’aide-mémoire (« méta-symboles »).

Le modèle pour trouver un point est le suivant :

\.

D'autres caractères spéciaux dans les expressions régulières correspondent à des éléments inhabituels du texte. Les sauts de ligne et les tabulations, par exemple, peuvent être saisis au clavier mais sont susceptibles de confondre les langages de programmation. Le caractère d'échappement est utilisé ici pour indiquer à l'analyseur de traiter le caractère suivant comme un caractère spécial plutôt que comme une lettre ou un chiffre ordinaire.

Caractères d'échappement spéciaux dans les expressions régulières

Substitution de chaîne

La substitution de chaînes est décrite en détail dans le paragraphe suivant, « Groupes et plages », mais l'existence de groupes « passifs » doit être mentionnée ici. Ce sont des groupes qui sont ignorés lors de la substitution, ce qui est très utile si vous souhaitez utiliser une condition « ou » dans un modèle, mais que vous ne souhaitez pas que ce groupe participe à la substitution.

Groupes et plages

Les groupes et les plages sont très, très utiles. Il est probablement plus facile de commencer par des plages. Ils vous permettent de spécifier un ensemble de caractères appropriés. Par exemple, pour vérifier si une chaîne contient des chiffres hexadécimaux (0 à 9 et A à F), vous utiliserez la plage suivante :

Pour vérifier le contraire, utilisez une plage négative, qui dans notre cas correspond à n'importe quel caractère à l'exception des chiffres de 0 à 9 et des lettres de A à F :

[^A-Fa-f0-9]

Les groupes sont le plus souvent utilisés lorsqu'une condition « ou » est nécessaire dans un modèle ; lorsque vous devez faire référence à une partie d'un modèle à partir d'une autre partie de celui-ci ; et aussi lors du remplacement de chaînes.

Utiliser « ou » est très simple : le modèle suivant recherche « ab » ou « bc » :

Si dans une expression régulière il est nécessaire de faire référence à l'un des groupes précédents, vous devez utiliser \n , où au lieu de n remplacer le numéro du groupe souhaité. Vous souhaiterez peut-être un motif qui correspond aux lettres « aaa » ou « bbb » suivies d'un chiffre, puis des trois mêmes lettres. Ce modèle est implémenté à l'aide de groupes :

(aaa|bbb)+\1

La première partie du motif recherche « aaa » ou « bbb », combinant les lettres trouvées en groupe. Ceci est suivi d'une recherche d'un ou plusieurs chiffres (+), et enfin de \1. La dernière partie du modèle fait référence au premier groupe et recherche la même chose. Il recherche une correspondance avec le texte déjà trouvé par la première partie du modèle, pas une correspondance avec celui-ci. Ainsi, "aaa123bbb" ne satisfera pas au modèle ci-dessus puisque \1 recherchera "aaa" après le nombre.

L'un des outils les plus utiles dans les expressions régulières est la substitution de chaînes. Lors du remplacement de texte, vous pouvez référencer le groupe trouvé en utilisant $n . Supposons que vous souhaitiez mettre en évidence tous les mots « souhait » dans le texte en gras. Pour ce faire, vous devez utiliser une fonction de remplacement d'expression régulière, qui pourrait ressembler à ceci :

Remplacer(modèle, remplacement, sujet)

Le premier paramètre ressemblera à ceci (vous aurez peut-être besoin de quelques caractères supplémentaires pour cette fonction particulière) :

([^A-Za-z0-9])(souhait)([^A-Za-z0-9])

Il trouvera toutes les occurrences du mot « souhait » ainsi que les caractères précédents et suivants, à condition qu'il ne s'agisse pas de lettres ou de chiffres. Votre substitution pourrait alors ressembler à ceci :

$1$2$3

Il remplacera la chaîne entière trouvée à l'aide du modèle. Nous commençons à remplacer par le premier caractère trouvé (qui n'est ni une lettre ni un chiffre), en le marquant $1 . Sans cela, nous supprimerions simplement ce caractère du texte. Il en va de même pour la fin de la substitution (3$). Au milieu, nous avons ajouté une balise HTML pour le gras (bien sûr, vous pouvez utiliser CSS ou ), en leur attribuant le deuxième groupe trouvé à l'aide du modèle ($2).

Les expressions régulières sont un moyen largement utilisé pour décrire des modèles de recherche de texte et vérifier si le texte correspond à un modèle. Des métacaractères spéciaux permettent de préciser, par exemple, que vous recherchez une sous-chaîne au début de la chaîne d'entrée ou un certain nombre de répétitions de la sous-chaîne.

À première vue, les expressions régulières semblent effrayantes (d'accord, au deuxième coup d'œil, elles semblent encore plus effrayantes ;)).

Je vous recommande fortement de « jouer » avec le programme de démonstration pour Windows REStudio fourni dans le kit de distribution - cela vous permettra de mieux comprendre le principe des expressions régulières et de déboguer vos propres expressions. TestREx comprend également de nombreux exemples d'expressions.

Vous trouverez ci-dessous une description d'un sous-ensemble de syntaxe d'expression régulière qui fonctionne dans presque toutes les implémentations et qui est prise en charge par ma bibliothèque Delphi, qui est incluse en tant que standard dans Lazarus (Free Pascal).

Commençons notre introduction aux expressions régulières !

Comparaison simple

Tout caractère correspond à lui-même, à moins qu'il n'appartienne aux métacaractères spéciaux décrits ci-dessous.

La séquence de caractères correspond à la même séquence dans la chaîne d'entrée, donc le motif bluh correspondra à la sous-chaîne bluh dans la chaîne d'entrée. Jusqu'à présent, tout est simple, n'est-ce pas ?

Si les métacaractères ou les séquences d'échappement doivent être traités comme des caractères normaux, ils doivent être précédés d'un caractère \, par exemple, le métacaractère ^ correspond généralement au début des lignes, cependant, s'il est écrit comme \^, il correspondra au caractère ^, \ \ correspond à \ etc.

Exemples :

foobar trouve 'foobar' \^FooBarPtr trouve '^FooBarPtr'

Séquences d'échappement

N'importe quel caractère peut être spécifié à l'aide d'une séquence d'échappement, comme cela se fait en C ou Perl : \n signifie le début d'une ligne, \t signifie une tabulation, etc. En général, \xnn , où nn est une séquence de caractères hexadécimaux. chiffres, signifie caractère avec le code ASCII nn. Si vous devez spécifier un caractère codé sur deux octets (Unicode), utilisez le format \x(nnnn) , où nnnn représente un ou plusieurs chiffres hexadécimaux.

\xnn caractère avec code hexadécimal nn \x(nnnn) caractère avec code hexadécimal nnnn (plus d'un octet ne peut être spécifié qu'en mode (tregexpr_interface.html#unicode))| \t tabulation (HT/TAB), vous pouvez aussi \x09 \n nouvelle ligne (NL), vous pouvez aussi \x0a \r retour chariot (CR), vous pouvez aussi \x0d| \f traduction au format (FF), vous pouvez également \x0c| \a appel (BEL), vous pouvez aussi \x07| \e escape (ESC), également \x1b|

Exemples :

foo\x20bar trouve 'foo bar' (notez l'espace au milieu) \tfoobar trouve 'foobar' précédé d'une tabulation

Listes de symboles

Vous pouvez définir une liste en plaçant les caractères entre . La liste correspondra à n’importe quel caractère qui y figure.

Si le premier caractère de la liste (immédiatement après [) est ^, alors une telle liste correspond à tout caractère non répertorié dans la liste.

Exemples :

foobr trouve 'foobar', 'foober', etc. mais pas 'foobbr', 'foobcr', etc.

foob[^aeiou]r trouve 'foobbr', 'foobcr', etc. mais pas 'foobar', 'foober', etc.

Dans une liste, le caractère - peut être utilisé pour définir des plages de caractères, par exemple a à z représente tous les caractères compris entre a et z inclus.

Exemples :

Si vous devez inclure le caractère lui-même dans la liste, placez-le au début ou à la fin de la liste, ou faites-le précéder d'un \ . Si vous devez inclure le caractère ] dans la liste, placez-le au tout début ou faites-le précéder d'un \ .

[-az] "a", "z" et "-" "a", "z" et "-" "a", "z" et "-" les 26 petites lettres latines de "a" à "z" [\n-\x0D] #10, #11, #12, #13.

Chiffre [\d-t], "-" ou "t".

-a] caractère de la plage "]".."a".

Métacaractères

Exemples :

Les métacaractères sont des caractères spéciaux qui constituent le concept le plus important dans les expressions régulières. Il existe plusieurs groupes de métacaractères.

Métacaractères - séparateurs de lignes

^ début de ligne $ fin de ligne \A début de texte \Z fin de texte. n'importe quel caractère dans la chaîne

^foobar trouve "foobar" seulement s'il est au début de la ligne foobar$ trouve "foobar" seulement s'il est à la fin de la ligne ^foobar$ trouve "foobar" seulement si c'est le seul mot de la ligne foob .r trouve "foobar", "foobbr", "foob1r", etc.

Le métacaractère ^ par défaut ne correspond qu'au début du texte saisi, et le métacaractère $ ne correspond qu'à la fin du texte. Les séparateurs de lignes internes présents dans le texte ne correspondront pas à ^ et $ .

Cependant, si vous devez traiter le texte comme multiligne, de sorte que ^ corresponde après chaque séparateur de ligne dans le texte et $ corresponde avant chaque délimiteur, vous pouvez alors inclure le modificateur /m.

Les métacaractères \A et \Z sont similaires à ^ et $, mais ils ne sont pas affectés par le modificateur /m, c'est-à-dire ils correspondent toujours uniquement au début et à la fin de l'intégralité du texte saisi.

$ correspond à la fin du texte saisi et également, si le modificateur /m est inclus, au point précédant immédiatement \x0D\x0A , \x0A ou \x0D (si vous utilisez la version Unicode de TRegExpr, alors également \x2028 ou \ x2029 ou \x0B ou \x0C ou \x85). Notez qu'il ne correspond pas à la séquence \x0D\x0A .

Correspond à n'importe quel caractère, mais si le modificateur r /s est désactivé, alors. ne correspond pas à \x0D\x0A et \x0A et \x0D (si vous utilisez la version Unicode de TRegExpr, il ne correspond pas à \x2028 et \x2029 et \x0B et \x0C et \x85).

Notez que ^.*$ (le modèle de la chaîne vide) ne correspond pas à la chaîne vide comme \x0D\x0A , mais il correspond à \x0A\x0D .

Vous pouvez reconfigurer le comportement ci-dessus lors du traitement de textes multilignes - consultez les descriptions des propriétés LineSeparators et LinePairedSeparator, par exemple, vous pouvez reconfigurer pour utiliser uniquement les séparateurs de ligne Unix \n ou uniquement les séparateurs DOS/Windows \r\n ou les séparateurs mixtes (ou configuré par défaut) ou même définir vos propres séparateurs de lignes !

Métacaractères - listes standard de caractères

\w caractère alphanumérique ou "_" \W not \w \d caractère numérique \D not \d \s tout caractère "espace blanc" (la valeur par défaut est [ \t\n\r\f]) \S not \ s

Les listes standards \w , \d et \s peuvent également être utilisées dans les listes de caractères.

Exemples :

foob\dr trouve "foob1r", ""foob6r", etc. mais pas "foobar", "foobbr", etc. foob[\w\s]r trouve "foobar", "foob r", " foobbr" etc. mais pas "foob1r", "foob=r" etc.

Métacaractères - options

Vous pouvez définir une liste d'options à l'aide du métacaractère | pour les séparer, par exemple fee|fie|foe correspondra à fee ou fie ou foe , (identique à f(e|i|o)e). Comme première option, tout depuis le métacaractère précédent (ou [ ou depuis le début de l'expression jusqu'au premier métacaractère | est perçu, comme la dernière option - tout depuis le dernier | jusqu'à la fin de l'expression ou jusqu'au métacaractère le plus proche) . Habituellement, pour éviter toute confusion, l'ensemble des options est toujours mis entre parenthèses, même si cela pourrait être fait sans.

Les options sont essayées en commençant par la première et les tentatives sont terminées dès qu'il est possible d'en sélectionner une dans laquelle toute la partie suivante de l'expression correspond (pour plus de détails, voir le mécanisme de fonctionnement). Cela signifie que les variantes ne fourniront pas nécessairement un comportement gourmand. Par exemple, si vous appliquez l'expression foo|foot à la chaîne d'entrée barefoot , il trouvera foo car c'est la première option qui permet à l'expression entière de correspondre.

Notez que le métacaractère | est perçu comme un caractère ordinaire dans des listes de caractères, par exemple, cela signifie exactement la même chose que .

Exemples :

foo(bar|foo) correspond à "foobar" ou "foofoo".

Métacaractères - sous-expressions

Les métacaractères (...) peuvent également être utilisés pour spécifier des sous-expressions

  • Après avoir terminé la recherche d'une expression, vous pouvez accéder à n'importe quelle sous-expression à l'aide des propriétés MatchPos, MatchLen et Match, et également substituer des sous-expressions dans un modèle à l'aide de la méthode Substitute).

Les sous-expressions sont numérotées de gauche à droite, dans l'ordre dans lequel apparaissent les parenthèses ouvrantes.

La première sous-expression porte le numéro 1 (l'expression entière est 0" , elle est accessible dans Substitute soit $0" ou $&).

Exemples :

(foobar)(8,10) trouve une chaîne contenant 8, 9 ou 10 copies de "foobar" foob(|a+)r trouve "foob0r", "foob1r", "foobar", "foobaar", "foobaar", etc. .

Métacaractères – backlinks

Les métacaractères \1 à \9 sont traités comme des backlinks. \ .

Exemples :

correspond à la sous-expression trouvée précédemment #

Modificateurs

(.)\1+ trouve "aaaa" et "cc". (.+)\1+ correspond également à "abab" et "123123" ([""]?)(\d+)\1 correspond à "13" (entre guillemets doubles), ou "4" (entre guillemets simples) ou 77 (sans les guillemets), etc.

Les modificateurs sont utilisés pour modifier les modes de fonctionnement de TRegExpr.

Vous pouvez modifier les modificateurs de plusieurs manières.

Tout modificateur peut être modifié à l'aide d'une construction spéciale (?...) à l'intérieur d'une expression régulière.

Vous pouvez également attribuer une valeur à la propriété correspondante de l'instance d'objet TRegExpr (par exemple, ModifierX pour modifier le modificateur /x ou ModifierStr pour modifier plusieurs modificateurs à la fois). Les valeurs par défaut pour les nouvelles instances d'objets TRegExpr sont définies dans , par exemple RegExprModifierX définit la valeur par défaut pour ModifierX.

je

Mode insensible à la casse (utilise par défaut la langue par défaut sélectionnée dans le système d'exploitation), (voir aussi InvertCase)

m

s

g

Pas un modificateur standard. En l'éteignant, vous faites passer tous les répéteurs en mode « non gourmand » (ce modificateur est activé par défaut). Ceux. Si vous le désactivez, alors tout + fonctionne comme + ? , * Comment *? etc.

x

Permet de formater le modèle pour le rendre plus facile à lire (voir description ci-dessous).

r

Le modificateur /x fait que TRegExpr ignore les espaces, les tabulations et les séparateurs de ligne, permettant ainsi au texte de l'expression d'être formaté. De plus, si le caractère # est rencontré, alors tous les caractères suivants jusqu'à la fin de la ligne sont traités comme un commentaire, par exemple :

((abc) # Commentaire 1 | # Les espaces dans l'expression sont également ignorés (efg) # Commentaire 2)

Naturellement, cela signifie que si vous devez insérer un espace, une tabulation, un séparateur de ligne ou un # dans une expression, alors en mode étendu (/x), cela ne peut être fait qu'en les faisant précéder de / ou en utilisant /xnn (dans les listes de caractères , tous ces personnages sont traités comme d'habitude )

Extensions Perl

(?imsxr-imsxr)

Vous permet de modifier les valeurs du modificateur

Exemples :

(?i)Saint-Pétersbourg trouve "Saint-Pétersbourg" et "Saint-Pétersbourg" (?i)Saint-(?-i)Pétersbourg trouve "Saint-Pétersbourg" mais pas "Saint-Pétersbourg" (?i)(Saint -)?Pétersbourg trouve "Saint-Pétersbourg" et "saint-pétersbourg" ((?i)Saint-)?Pétersbourg trouve "saint-pétersbourg", mais pas "saint-pétersbourg"

Les secrets des expressions régulières

Partie 1. Dialectes et capacités. Écrire des expressions régulières

Série de contenu :

1. Présentation. Utilisons-nous les expressions régulières à leur plein potentiel ?

Si vous réfléchissez à la question : « Qu'est-ce qu'une « expression régulière » en général ? », alors la réponse ne sera pas trouvée immédiatement. On peut dire qu'il s'agit d'un langage spécialisé pour décrire un modèle de caractères (séquence de caractères) pour la recherche dans des chaînes de texte. L'important ici est que lors de la recherche de correspondances, c'est une comparaison caractère par caractère qui est effectuée. L'auteur de l'encyclopédie des expressions régulières (Mastering Regular Expressions) Jeffrey Friedl (J.E.F. Friedl) conseille de développer l'habitude d'interpréter les expressions régulières de manière littérale. Par exemple, en regardant le motif "^cat", qui signifie "la ligne doit commencer par le mot chat", on pourrait penser que "une correspondance sera trouvée si nous sommes au début de la ligne et trouvons immédiatement le caractère c". suivi du caractère a, immédiatement suivi d'un symbole t". Cela vous permet d'évaluer le plus précisément possible la signification et l'essence d'une expression régulière.

La plupart des utilisateurs savent que pour effectuer une recherche, il suffit de saisir un exemple de mot. Par exemple, dans un navigateur Web, dans le champ « Rechercher », après avoir saisi « Linux », vous recevrez une longue liste de liens vers des pages dont le texte correspond au modèle « Linux » spécifié. Sur le système de fichiers local, utilisez la commande grep "Linux" ou les outils de recherche graphique.

Pas tous, mais de nombreux utilisateurs savent utiliser les métacaractères (* . ?) dans les modèles de recherche. Encore moins de gens connaissent la possibilité d'utiliser des modificateurs et d'autres outils sophistiqués pour construire des expressions régulières, c'est-à-dire dans de nombreux cas, à peine un tiers de la puissance du moteur d’expression régulière est utilisé. Pourquoi ne pas essayer d’augmenter l’efficacité ?

2. Différents dialectes d'expressions régulières. Conforme POSIX

De manière générale, il existe deux principaux dialectes (ou types) d'expressions régulières : simples et étendues. Dans le même temps, la frontière entre eux est conditionnelle et devient de moins en moins claire avec le temps.

Les programmes vi(m), sed, grep, less, ed, expr, lex ne comprennent que les expressions régulières simples, tandis que les utilitaires (g)awk, egrep, ainsi que les interprètes des langages Perl, Tcl, Python, comprennent les expressions régulières étendues. expressions. Dans le même temps, chacun des programmes a ses propres améliorations, c'est-à-dire des sous-dialectes d'expressions régulières sont créés. Examinons les similitudes et les différences entre ces dialectes.

2.1. Schéma général d'expression régulière

Généralement, une expression régulière se compose de trois parties principales :

  1. Ancre – définit la position du modèle dans une ligne de texte :
    • ^ – ancre définissant le début de la ligne ;
    • $ est une ancre qui définit la fin de la ligne.
  2. Un ensemble (séquence) de caractères – pour rechercher des correspondances dans des positions données d'une ligne de texte :
    • le caractère point (.) correspond à n'importe quel caractère arbitraire ;
    • les caractères alphanumériques et l'espace se représentent eux-mêmes ;
    • autres symboles - l'interprétation dépend du dialecte.
  3. Modificateur – définit le nombre de répétitions du caractère ou du jeu de caractères précédent (selon le dialecte) :
    • * – n'importe quel nombre de répétitions d'un caractère/ensemble, y compris zéro ;
    • ? – correspond à zéro ou à une instance d'un caractère/ensemble ;
    • + – correspond à une ou plusieurs instances d'un caractère/ensemble.

Exemple : vous devez retrouver toutes les directives permettant de définir les constantes de macro dans le code source C.

grep "^ *#define.*" *.c *.h

Il est pris en compte ici que n'importe quel nombre d'espaces ou aucun espace peut être inséré au début de la ligne de définition de la macro. La partie #define du modèle est littérale, c'est-à-dire chaque caractère est interprété « tel quel ». La dernière partie du motif signifie « n’importe quel symbole en n’importe quelle quantité ».

Notez que le caractère ^ est interprété comme une ancre marquant le début d'une ligne uniquement s'il s'agit du tout premier caractère du motif. De même, le caractère $ marque la fin d'une ligne, à condition qu'il s'agisse du tout dernier caractère du motif. Dans tous les autres cas, ces symboles deviennent littéraux, c'est-à-dire se représenter.

2.2. Définir des plages de caractères dans les expressions régulières

S'il est nécessaire de spécifier un caractère d'un certain groupe, par exemple uniquement un caractère numérique, ou uniquement une voyelle minuscule, ou uniquement des symboles de ponctuation, des crochets sont utilisés, dans lesquels les caractères requis sont définis. Ainsi:

  • – correspond à un caractère numérique d'un ensemble donné;
  • [аееоуыеюя] – correspond à l'une des voyelles répertoriées ;
  • [,.:;] – correspond à l’un des symboles de ponctuation.

Veuillez noter que dans ce dernier cas, le point entre crochets perd son statut particulier et ne désigne pas « n'importe quel caractère », mais le caractère « point » lui-même.

Les plages continues de caractères peuvent être écrites sous forme abrégée à l'aide d'un trait d'union : le premier exemple s'écrit plus commodément sous la forme . De plus, toute combinaison de plages et de caractères spécifiques est autorisée.

Il est également possible d'exclure des jeux de caractères spécifiés de la recherche, ce qui se fait comme suit :

  • [^0-9] – correspond à n'importe quel caractère sauf numérique ;
  • [^аеойоуыеюя] – correspond à n'importe quelle lettre qui n'est PAS une voyelle.

Nous nous familiariserons avec d'autres nuances de définition de plages de caractères entre crochets au cours du processus de leur application, et nous examinerons maintenant les modificateurs en utilisant l'exemple d'un modèle de recherche pour une adresse IP numérique.

2.3. Modificateurs du nombre de répétitions de caractères

La difficulté ici est que le modificateur * n'est pas adapté à la recherche d'une adresse IP - une tentative d'utiliser le modèle *\.*\.*\. entraînera des lignes contenant des éléments de type 2344.5657.11.00000, qui ne sont pas des adresses IP. Pour spécifier le nombre de répétitions des jeux de caractères, le modificateur \(min,max\) est utilisé. Sachant que chaque partie de l’adresse IP peut contenir de un à trois chiffres, on écrira le modificateur sous la forme \(1,3\). Les caractères de barre oblique inverse précédant les points doivent remplacer leur statut spécial en tant que métacaractère générique. Notez également que la valeur 0 n'est pas utilisée comme premier octet des adresses IP normales. En conséquence, nous obtenons le modèle de recherche suivant :

grep "\(0,2\)\.\(1,3\)\.\(1,3\)\.\(1,3\)" *.txt

Le modificateur \(min,max\) ne fonctionne que dans les expressions régulières simples. Vous ne pouvez pas utiliser \( \) dans les expressions régulières étendues, mais vous pouvez utiliser un modificateur ? comme équivalent de l'expression \(0,1\), et le modificateur + comme équivalent de l'expression \(1,\). Dans le second cas, il n'y a pas de valeur numérique après la virgule – cela signifie que le nombre maximum de correspondances n'est pas limité.

2.4. Mémoriser et réutiliser un élément de modèle

Ce mécanisme ne fonctionne également que dans les expressions régulières simples. (Cependant, dans les langages de programmation Perl, Python, etc., ce mécanisme est pris en charge - la frontière entre les dialectes devient de moins en moins distinguable, vous vous souvenez ?)

Dans les expressions régulières simples, les parties du modèle incluses dans la construction \(\) sont mémorisées et numérotées, après quoi elles peuvent être réutilisées. Au total, vous pouvez mémoriser jusqu'à neuf motifs numérotés. L'exemple le plus illustratif de l'utilisation du mécanisme de mémorisation est la recherche de palindromes (mots qui se lisent de la même manière aussi bien de gauche à droite que de droite à gauche) :

  • \(\)\(\)\2\1 – pour les palindromes à cinq lettres (par exemple, niveau, rotor, madame, etc.)
  • \(\)\(\)\(\)\3\2\1 – pour les palindromes à six lettres (par exemple, plus rouge, succus, terret, etc.)

2.5. Conforme POSIX

Le standard POSIX divise également les expressions régulières en deux catégories : BRE (Basic Regular Expressions) et ERE (Extended Regular Expressions). Les métacaractères sont pris en charge dans les deux catégories. et *, ancres ^ et $, regroupant les caractères entre parenthèses (pour BRE, les parenthèses sont échappées avec une barre oblique inverse), appliquant les quantificateurs \(min,max\) aux groupes entre parenthèses. La mémorisation et la réutilisation de \1...\9 ne sont prises en charge que par la catégorie BRE, et les quantificateurs + et ? et le construit de choix – catégorie ERE uniquement.

La norme POSIX utilise le concept de contexte local (locale) - un ensemble de paramètres qui décrivent les règles linguistiques et culturelles : format de date et d'heure, interprétation des caractères d'encodage actifs, etc. Cela ne s’applique pas directement aux expressions régulières, mais cela affecte leur fonctionnement. Lorsque vous travaillez dans un contexte local avec le codage UTF-8, adopté dans presque toutes les distributions modernes, les caractères de l'alphabet russe et leurs plages sont traités correctement, c'est-à-dire Vous pouvez spécifier des plages [a-z] et [A-Z] dans les modèles de recherche.

3. Exemples de composition d'expressions régulières utiles

Pour créer des expressions régulières fonctionnant correctement, la théorie seule ne suffit pas. Il faut apprendre non seulement à construire et rédiger un modèle, mais aussi à prendre pleinement en compte le contexte dans lequel il sera comparé. L'écriture et l'amélioration d'un modèle sont un processus itératif au cours duquel deux tâches principales sont résolues : d'une part, obtenir toutes les lignes requises, sans manquer celles qui, selon le plan, auraient dû correspondre, mais pour une raison quelconque ne l'ont pas été. correspondre; d'autre part, excluez toutes les lignes inutiles, y compris celles qui, selon le plan, devraient être supprimées, mais qui, pour une raison quelconque, coïncidaient.

3.1. Un exemple de modèle de recherche d'une somme d'argent écrite au format "10 000 roubles 00 kopecks".

\(1,\) frotter\. \(2\) kopecks\.

Clarification nécessaire : si un modificateur comme \(min,max\) manque à la fois d'une virgule et d'une valeur maximale, alors cette construction spécifie le nombre exact de répétitions attendues de l'élément du modèle. Dans notre exemple, exactement deux caractères numériques sont définis pour représenter les kopecks.

3.2. Un exemple de modèle de recherche d'une chaîne d'URL correspondant à une ressource Web sur Internet :

http://\(1,\)\.[-a-zA-Z0-9_]\(1,\)/*

Précision nécessaire : un trait d'union perd sa signification particulière s'il est spécifié à la toute première position immédiatement après le crochet ouvrant dans une plage. Ce modèle peut également être utilisé pour rechercher des chaînes d'URL « exotiques », telles que http://my.home-server/

Dans un format d'expression régulière étendue, ce modèle pourrait être écrit de manière plus compacte :

http://+\.[-a-zA-Z0-9_]+/*

Cette notation est comprise, par exemple, par les utilitaires egrep et awk.

3.3. Le modèle de recherche de n'importe quelle balise HTML semble étonnamment simple :

<[^>]+>

Correspond à n’importe quelle séquence de caractères à l’exception d’un ou plusieurs > entourés de crochets angulaires. Autrement dit, une balise à un seul caractère sera également trouvée

Et des balises plus verbeuses comme


.

3.4. Option de modèle pour rechercher des dates

Les expressions régulières avancées vous permettent d'écrire un modèle quelque peu fastidieux, mais néanmoins fonctionnel, pour rechercher des dates qui ressemblent au « 13 novembre 2009 » :

? (janvier|février|mar|avril|mai|juin|juil|août|septembre|oct|nov|déc).* g\.

L'inconvénient de ce modèle est qu'il ne peut pas être utilisé pour rechercher des dates de l'histoire ancienne, par exemple « 13 novembre 245 ». ou 1er janvier 88 », mais il est tout à fait adapté pour travailler avec des documents modernes (tenez compte du contexte de recherche !).

3.5. Application pratique des parties numérotées du modèle

Dans la section précédente, j'ai déjà donné un exemple de modèle de recherche de palindromes. Sa fonctionnalité peut également être légèrement améliorée en réécrivant l'expression comme suit :

\(.\)\(.\)\(.\)\3\2\1

En utilisant ce modèle, vous pouvez trouver des palindromes à six caractères non seulement en anglais, mais également en russe et dans d'autres langues, ainsi que des séquences de caractères non alphabétiques, par exemple /*!!*/

Une manière plus pratique d'utiliser les parties mémorisées et numérotées du modèle consiste à rechercher des mots répétés à proximité, ce qui vous permet de détecter des erreurs courantes (fautes de frappe) dans les textes comme « pour pour ». Le modèle peut s'écrire ainsi :

\<\(..*\)\> \<\1\>

Deux autres éléments d'expression régulière sont utilisés ici : \< для обозначения начальной границы слова и \>pour indiquer la limite finale d'un mot. Ainsi, nous nous souvenons uniquement de mots individuels et non d’une séquence de caractères. L'expression ..* correspond à tout mot composé d'au moins un caractère. De ce fait, nous pourrons retrouver des fautes de frappe de répétition telles que « et et », « pas pas », « pour pour », etc.

3.6. Limiter la taille de la partie correspondante du motif

Une autre caractéristique du « caractère » des expressions régulières est qu’elles sont incroyablement « gourmandes », c’est-à-dire efforcez-vous de faire correspondre une chaîne aussi longue que possible. À cause de cette « cupidité », des problèmes inattendus peuvent survenir. Par exemple, il existe un modèle permettant de rechercher un nombre quelconque de caractères entre guillemets :

".*"

Les chaînes de recherche ressemblent à ceci :

"Petrov" "agent de sécurité" "Ivanov" "département d'approvisionnement" "transitaire" "Sidorov" "administration" "directeur"

Si la tâche consistait à extraire uniquement le premier argument (nom de famille de l'employé) des chaînes données, alors le modèle proposé ci-dessus ne l'exécutera pas correctement, puisque la deuxième citation du modèle correspond à la dernière citation de la chaîne (en raison du désir pour obtenir la correspondance maximale). Changer le modèle :

".*" ".*"

ne résout le problème que pour la première ligne, et dans les deuxième et troisième, le lieu de travail est également attaché au nom de famille - encore une fois, ce n'est pas ce dont nous avons besoin !

Ce problème peut être résolu correctement en utilisant une expression régulière qui correspond au plus court de tous les fragments de chaîne possibles, situés entre deux guillemets :

"[^"]*"

Ici, le guillemet d'ouverture doit être suivi d'un nombre quelconque de caractères autres que les guillemets jusqu'à ce que le guillemet de fin soit rencontré.

4. Conclusion

Même à partir des exemples, loin d'être les plus complexes, décrits dans cet article, vous avez pu comprendre à quel point les capacités des expressions régulières sont riches et variées. Vous pouvez même considérer le format d'enregistrement de leurs modèles comme une sorte de langage de programmation, apprenant à penser et à écrire, dans lequel vous vous épargnerez beaucoup de travail monotone et fastidieux.

Le premier article donnait une idée générale des expressions régulières et de leur portée, ainsi qu'un bref aperçu des caractéristiques de leurs dialectes. Des exemples de composition d'expressions régulières pour résoudre divers problèmes ont été examinés.

La suite de la série sera consacrée aux travaux pratiques avec les expressions régulières dans des programmes et des environnements linguistiques spécifiques.

Ressources à télécharger

static.content.url=http://www.site/developerworks/js/artrating/

Numéro d'article=487264

ArticleTitle=Secrets des expressions régulières : Partie 1. Dialectes et capacités. Écrire des expressions régulières

Que sont les expressions régulières ?

Si vous avez déjà travaillé avec la ligne de commande, vous avez probablement utilisé des masques de nom de fichier. Par exemple, pour supprimer tous les fichiers du répertoire courant commençant par la lettre "d", vous pouvez écrire

Les expressions régulières sont un outil similaire, mais beaucoup plus puissant, pour rechercher des chaînes, les tester par rapport à un modèle et effectuer d'autres travaux similaires. Le nom anglais de cet instrument est Expressions régulières ou juste Expression régulière. À proprement parler, les expressions régulières sont un langage spécial pour décrire des modèles de chaînes.

L'implémentation de cet outil varie selon les langages de programmation, mais pas beaucoup. Dans cet article, nous nous concentrerons principalement sur l’implémentation des expressions régulières compatibles Perl.

Bases de la syntaxe

Tout d’abord, il convient de noter que toute chaîne elle-même est une expression régulière. Ainsi, l'expression

Haha correspondra évidemment à la chaîne « Haha » et seulement ça. Les expressions régulières sont sensibles à la casse, donc la chaîne « haha ​​» (minuscule) ne correspondra plus à l'expression ci-dessus.

Cependant, vous devez être prudent ici : comme dans tout langage, les expressions régulières comportent des caractères spéciaux qui doivent être échappés. Voici leur liste :

. ^ $ * + ? ( ) \ | (). L'échappement se fait de la manière habituelle - en ajoutant \ avant le caractère spécial.

Jeu de caractères

Supposons que nous voulions trouver toutes les interjections dans un texte qui indiquent le rire. Juste

Haha ne nous conviendra pas - après tout, "Hehe", "Hoho" et "Hihi" n'en relèveront pas. Et le problème avec le cas de la première lettre doit être résolu d’une manière ou d’une autre.

Ici, les ensembles nous viendront en aide - au lieu de spécifier un caractère spécifique, nous pouvons écrire une liste complète, et si l'un des caractères répertoriés apparaît à l'endroit spécifié dans la chaîne examinée, la chaîne sera considérée comme appropriée. Les ensembles sont écrits entre crochets - motif

Correspondra à l'un des caractères "a", "b", "c" ou "d".

Ensemble intérieur b Ô La plupart des caractères spéciaux n'ont pas besoin d'être échappés, mais d'utiliser

\ devant eux ne sera pas considéré comme une erreur. Il faut quand même échapper les caractères « \ » et « ^ », et, de préférence, « ] » (il s'agit donc de l'un des caractères « ] » ou « [ », tandis que [x] est exclusivement la séquence « [ x] »). Le comportement apparemment inhabituel des expressions régulières avec le caractère « ] » est en réalité déterminé par des règles bien connues, mais il est beaucoup plus facile d'échapper simplement à ce caractère que de s'en souvenir. De plus, le symbole « - » doit être échappé ; il est utilisé pour définir les plages (voir ci-dessous).

Si immédiatement après

[notez le symbole ^ , alors l'ensemble prendra le sens opposé - tout symbole autre que ceux indiqués sera considéré comme approprié. Ainsi, le motif [^xyz] correspond à n'importe quel caractère sauf « x », « y » ou « z ».

Donc, en appliquant cet outil à notre cas, si nous écrivons

[Xx][aoie]x[aoie] , alors chacune des lignes « Haha », « hehe », « hihi » et même « Hoho » correspondra au motif.

Classes de caractères prédéfinies

Pour certains ensembles assez souvent utilisés, il existe des modèles spéciaux. Ainsi, pour décrire tout caractère d'espacement (espace, tabulation, saut de ligne), utilisez

\s , pour les nombres - \d , pour les caractères latins, les nombres et les traits de soulignement "_" - \w .

S'il est nécessaire de décrire un personnage, un point est utilisé pour cela -

Si les classes spécifiées sont écrites avec une lettre majuscule (\S , \D , \W), leur signification changera alors à l'opposé : tout caractère autre qu'un espace, tout caractère qui n'est pas un nombre et tout caractère autre que le Alphabet latin, chiffres ou trait de soulignement, respectivement.

Aussi, à l’aide d’expressions régulières, il est possible de vérifier la position d’une ligne par rapport au reste du texte. Expression

\b désigne une limite de mot, \B est une limite de non-mot, ^ est le début du texte et $ est la fin. Ainsi, selon le modèle \bJava\b, les 4 premiers caractères seront trouvés dans la ligne « Java et JavaScript », et selon le modèle \bJava\B, les 10ème au 13ème caractères seront trouvés (dans le cadre du mot « JavaScript »).

Gammes

Vous devrez peut-être désigner un ensemble contenant des lettres, par exemple de « b » à « f ». Au lieu d'écrire

[bvgdezziklmnoprstuf], vous pouvez utiliser le mécanisme de plage et écrire [b-f] . Ainsi, le motif x correspond à la chaîne « xA6 », mais ne correspond pas à « xb9 » (d'une part, du fait que seules les majuscules sont indiquées dans la plage, et d'autre part, du fait que 9 n'est pas inclus dans l'intervalle 0 -8).

Le mécanisme des gammes est particulièrement pertinent pour la langue russe, car pour elle il n'existe pas de construction similaire

\w . Pour désigner toutes les lettres de l'alphabet russe, vous pouvez utiliser le motif [а-яА-ЯеО] . Veuillez noter que la lettre « ё » n'est pas incluse dans la gamme générale de lettres et doit être spécifiée séparément.

Quantificateurs (indiquant le nombre de répétitions)

Revenons à notre exemple. Et si l'interjection « riant » avait plus d'une voyelle entre les x, comme « Haahaaaa » ? Notre ancienne saison régulière ne pourra plus nous aider. Ici, nous devrons utiliser des quantificateurs.

Notez que le quantificateur ne s’applique qu’au caractère qui le précède.

Certaines constructions fréquemment utilisées ont reçu des notations spéciales dans le langage des expressions régulières :

Ainsi, avec l'aide de quantificateurs, nous pouvons améliorer notre modèle d'interjections pour

[Xx][aoeee]+x[aoeee]* , et il pourra reconnaître les lignes "Haaha", "heeeeeeh" et "Hihii".

Quantification paresseuse

Supposons que nous soyons confrontés à la tâche de trouver toutes les balises HTML dans une chaîne

Tproger- mon Chéri site sur la programmation !

La solution évidente

<.*>cela ne fonctionnera pas ici - il trouvera la chaîne entière, car il commence et se termine par une balise de paragraphe. Autrement dit, le contenu de la balise sera considéré comme la chaîne p> Tproger- mon Chéri site sur la programmation !

Cela est dû au fait que par défaut, le quantificateur fonctionne selon ce qu'on appelle. cupide algorithme - essaie de renvoyer la chaîne la plus longue possible qui remplit la condition. Il existe deux manières de résoudre le problème. La première consiste à utiliser l’expression

<[^>]*> , ce qui empêchera que le crochet droit soit considéré comme le contenu de la balise. La seconde est de déclarer le quantificateur non gourmand, mais paresseux. Est-ce fait en ajoutant à droite du quantificateur de caractère ?<.*?> .

. Ceux. pour rechercher toutes les balises, l'expression deviendra

Quantification jalouse Parfois, pour augmenter la vitesse de recherche (notamment dans les cas où la chaîne ne correspond pas à l'expression régulière), vous pouvez empêcher l'algorithme de revenir aux étapes de recherche précédentes afin de trouver des correspondances possibles pour le reste de l'expression régulière. Ça s'appelle quantification. Le quantificateur est rendu jaloux en ajoutant le symbole à sa droite

Une autre utilisation de la quantification jalouse consiste à exclure les correspondances indésirables. Ainsi, le modèle ab*+a dans la chaîne « ababa » correspondra uniquement aux trois premiers caractères, mais pas aux caractères du troisième au cinquième, car le caractère "a", qui est en troisième position, a déjà été utilisé pour le premier résultat.

Groupes de supports

Pour notre modèle d'interjection « riant », il ne reste plus qu'à prendre en compte que la lettre « x » peut apparaître plus d'une fois, par exemple « Hahahahaaahaahoooo », et peut même se terminer par la lettre « x ». Vous devrez probablement utiliser un quantificateur de groupe ici

[aioe]+x, mais si on écrit simplement [aioe]x+ , alors le quantificateur + ne s'appliquera qu'au caractère "x" et non à l'expression entière. Pour résoudre ce problème, l'expression doit être placée entre parenthèses : ([aioe]x)+ .

Ainsi notre expression devient

[Хх]([аое]х?)+ - il y a d'abord un « x » majuscule ou minuscule, puis un nombre arbitraire non nul de voyelles, qui (éventuellement, mais pas nécessairement) sont entrecoupées d'un seul « x » minuscule . Cependant, cette expression ne résout le problème que partiellement - cette expression inclura également des lignes telles que, par exemple, « hihaheh » - quelqu'un peut rire comme ça, mais l'hypothèse est très douteuse. Évidemment, nous ne pouvons utiliser un ensemble de toutes les voyelles qu’une seule fois, et nous devons alors nous fier d’une manière ou d’une autre au résultat de la première recherche. Mais comment ?...

Mémorisation du résultat de la recherche par groupe (feedback)

Il s'avère que le résultat de la recherche d'un groupe de crochets est écrit dans une cellule mémoire distincte, accessible pour être utilisée dans les parties ultérieures de l'expression régulière. Pour en revenir à la tâche de recherche de balises HTML sur une page, nous devrons peut-être non seulement trouver les balises, mais également connaître leur nom. Une expression régulière peut nous aider avec cela

<(.*?)> .

Tproger- mon Chéri site sur la programmation !

Résultat de la recherche pour toutes les expressions régulières : "

», « », «», « », «», «

».
Résultat de recherche pour le premier groupe : "p", "b", "/b", "i", "/i", "/i", "/p".

Le résultat d'une recherche de groupe peut être référencé à l'aide de l'expression

\n , où n est un nombre compris entre 1 et 9. Par exemple, l'expression (\w)(\w)\1\2 correspond aux chaînes « aaaa », « abab », mais ne correspond pas à « aabb ».

Si une expression est placée entre parenthèses uniquement pour lui appliquer un quantificateur (il n'est pas prévu de mémoriser le résultat de la recherche pour ce groupe), alors la première parenthèse doit être ajoutée immédiatement

?: , par exemple (?:+\w) .

En utilisant ce mécanisme, nous pouvons réécrire notre expression sous la forme

[Xx]([aoie])x?(?:\1x?)* .

Transfert

Pour vérifier si une chaîne satisfait au moins un des modèles, vous pouvez utiliser un analogue de l'opérateur booléen OU, qui s'écrit à l'aide du symbole

|

. Ainsi, le modèle Anna|Loneliness comprend respectivement les lignes « Anna » et « Loneliness ». Il est particulièrement pratique d’utiliser des énumérations entre parenthèses. Ainsi, par exemple, (?:a|b|c|d) est tout à fait équivalent (dans ce cas, la deuxième option est préférable en raison des performances et de la lisibilité).

En utilisant cet opérateur, nous pouvons ajouter à notre expression régulière pour trouver des interjections la capacité de reconnaître des rires comme « Ahahaah » - le seul sourire qui commence par une voyelle :

[Xx]([aoie])x?(?:\1x?)*|[Aa]x?(?:ah?)+

Services utiles

Vous pouvez pratiquer et/ou tester votre expression régulière sur du texte sans écrire de code en utilisant des services tels que RegExr, Regexpal ou Regex101. Ce dernier fournit en outre de brèves explications sur le fonctionnement du système régulier.

Vous pouvez comprendre comment fonctionne une expression régulière qui vous tombe entre les mains à l'aide du service Regexper - il peut créer des diagrammes compréhensibles à l'aide d'une expression régulière.

0

0

RegExp Builder est un constructeur visuel de fonctions JavaScript permettant de travailler avec des expressions régulières.

J'ai décidé d'écrire un aide-mémoire sur les expressions régulières. Peut-être qu'un jour je les oublierai. De plus, cet article peut être considéré comme une continuation de ma série de tutoriels Perl.

1. Introduction

Quelques mots pour ceux qui ne savent pas trop de quoi nous parlons. Avez-vous déjà vu des masques de noms de fichiers - toutes sortes de *.html, nom de fichier.(txt|csv), etc. ? Ainsi, les expressions régulières sont les mêmes « masques », mais en plus complexes. Entre de bonnes mains, les expressions régulières peuvent être un outil incroyablement puissant. D'une manière ou d'une autre, ils sont utilisés dans 95 % de mes scripts.

De nombreuses personnes pensent, non sans raison, que les expressions régulières constituent davantage un langage de programmation indépendant qu'une partie d'un langage quelconque. Les expressions régulières se trouvent dans les fichiers de configuration Perl, PHP, Python, JavaScript, Apache... Selon le langage, il peut y avoir de légères différences dans la syntaxe des expressions régulières, mais les idées de base sont les mêmes.

Par conséquent, malgré le fait que tous les exemples de la note soient écrits en Perl, les informations fournies seront également utiles aux programmeurs qui utilisent un autre langage dans leur travail. Par exemple, ce code en PHP :
if (preg_match ("//" , $text ) ) (
// le texte contient des chiffres
) autre (
}

// il n'y a pas de chiffres dans le texte

et celui-ci en Perl :
si ($texte =~ // ) (
// le texte contient des chiffres

}

faire la même chose. Comme vous pouvez le deviner d'après les commentaires dans le code, une vérification est effectuée pour voir si la chaîne $text contient au moins un chiffre.

2. Exemples simples

Comme toujours, nous apprendrons des exemples. Crochets dans les expressions régulières, cela signifie "l'un des caractères répertoriés doit être ici". Par exemple, l'expression ci-dessus correspond à toute chaîne contenant au moins un chiffre. Semblable à l'expression correspond à n’importe quelle chaîne contenant au moins une des trois premières lettres de l’alphabet latin. Pour représenter n'importe quel personnage, sauf spécifié, l'entrée est utilisée [^abcdef], c'est-à-dire avec symbole du couvercle immédiatement après le crochet ouvrant.

Supposons que nous devions vérifier si une chaîne contient un caractère de l'alphabet latin. Ce n’est pas tout à fait pratique de lister les 26 lettres, n’est-ce pas ? Surtout dans de tels cas, dans les expressions régulières, vous pouvez utiliser tiret entre crochets pour désigner un ensemble ordonné de caractères. Expression Toute chaîne contenant au moins une lettre minuscule de l'alphabet latin correspondra. Par analogie, l'exemple donné précédemment avec des nombres peut s'écrire plus brièvement :

et celui-ci en Perl :
si ($texte =~ // ) (
// le texte contient des chiffres
# il n'y a pas de chiffres dans le texte
}

Et quelques autres exemples :

et celui-ci en Perl :
# le texte contient des chiffres et/ou des lettres minuscules
# approprié : abc, ZZaZZ, ===17
# ne convient pas : ÉCHEC ÉPIQUE, @^*!@#
}

si ($texte =~ /[^0-9]/ ) (
# le texte contient des caractères autres que des chiffres
# convient : abc, 123abc456, 0x1111111111
# ne convient pas : 123, 123456, 9999999999
}

et celui-ci en Perl :
# le texte contient des lettres de l'alphabet latin
# approprié : ___Abba___, zyx
# ne convient pas : 0123, ^_^
}

et celui-ci en Perl :
# le texte contient des chiffres et des lettres de A à F
# approprié : ***777***, DeadC0de, intel, 0_o
# ne convient pas : Xor, wiki
}

Compliquons la tâche. Nous devons maintenant vérifier non seulement la présence ou l'absence de certains caractères, mais aussi si la chaîne correspond à un certain format. Voici quelques exemples simples :

si ($text =~ /num=/ ) (
# approprié : num=1, some_num=000, bebenum=2(&^*
# ne convient pas : NUM=1, my_num=-1, num=abc
}

si ($texte =~ / / ) {
# convient :
#zzz zzz
#
# ne convient pas :
#
#
}

Le lecteur attentif se demandera ce que cela signifie signe plus est-ce dans la dernière expression régulière ? Ce symbole signifie « un ou plusieurs caractères spécifiés avant ce plus ». Le symbole signifie presque la même chose étoile"depuis zéro jusqu'à n'importe quel nombre de caractères spécifié avant l'astérisque. Par exemple, l'expression A+ correspondra à une séquence d'un ou plusieurs caractères A, et l'expression * - n'importe quel nombre de chiffres, y compris aucun.

Parfois, le nombre de caractères doit être précisé plus précisément. Cela peut être fait en utilisant accolades. Par exemple, l'expression {8} correspond à n’importe quelle séquence d’exactement huit chiffres, et l’expression {3,8} — une séquence contenant de 3 à 8 caractères de l'alphabet latin.

Le numéro en deuxième position ne peut pas être précisé. C'est-à-dire l'expression {3,} peut également se produire. Cela signifie « au moins trois lettres minuscules de l’alphabet latin ». Expression {0,} complètement similaire à l'astérisque, et {1,} - un plus. Expression {0,1} peut être écrit plus brièvement en utilisant point d'interrogation.

Exemple (pas le plus simple, mais intéressant) :

si ($texte =~ // ) {
# convient :
#dfgd dfgdfg
#
# ne convient pas :
#
#
}

Si cet exemple vous fait bouillir le cerveau, il est temps de vous entraîner un peu avec les expressions régulières en écrivant des programmes de test. Sinon, une lecture plus approfondie vous laissera avec un désordre dans la tête. Si tout est clair jusqu’à présent, passons à autre chose.

3. Comment arracher un morceau de ligne ?

Symbole ligne verticale(alias "pipe" ou simplement "stick") dans les expressions régulières signifie "ou". Par exemple, l'expression {20}|{25} correspond à toutes les chaînes contenant 20 caractères latins ou 25 numéros d'affilée. Généralement, ce symbole est utilisé conjointement avec parenthèses, conçu pour regrouper des parties d'une expression régulière. Exemple:

si ($nom de fichier =~ /sauvegarde(19|20)(2)-(2)-(2)/) {
# approprié : sauvegarde 01/04/2011, sauvegarde 13/01/1999
# ne convient pas : sauvegarde 1873-12-12, sauvegarde 2101-07-07
}

Les parenthèses ont une autre fonction. Avec leur aide, vous pouvez déchirer des morceaux des lignes correspondantes. En PHP, le résultat est stocké dans la variable spécifiée par le troisième argument de la fonction preg_match. En Perl, les correspondances pour la 1ère, la 2ème...9ème paire de parenthèses sont stockées dans les variables $1, $2,..., $9. Mais il est plus pratique d'utiliser cette construction :

si (mon ($y, $m, $d) =
$nom de fichier =~ /sauvegarde((4))-((2))-((2))/) {
imprimer ;
}

La question est de savoir quel numéro rechercher une correspondance dans le tableau renvoyé si l'expression régulière contient imbriqué des parenthèses ? C'est simple : les correspondances sont renvoyées dans le même ordre que les parenthèses ouvrantes. Exemple:

mon $nom de fichier = "./dumps/backup2011-04-01.tgz";
$nom de fichier =~ /sauvegarde((20|19)(2))-((2))-((2))/;
imprimer "1 $, 2 $, 3 $, 4 $ \n";
# sortira : 2011, 20, 04, 01

Parfois, nous aimerions regrouper une partie d’une expression, mais ne pas la renvoyer. Pour ce faire, immédiatement après le crochet ouvrant, vous devez écrire séquence de point d'interrogation et de deux points. Exemple:

si (mon ($y, $m, $d) =
$nom de fichier =~ /sauvegarde((?:20|19)(2))-((2))-((2))/) {
imprimer "année = $y, mois = $m, jour = $d\n ";
}

Les parenthèses peuvent également être suivies d'un point d'interrogation, d'un plus ou d'un astérisque, indiquant que la construction entre parenthèses est facultative, doit être répétée plus d'une fois ou doit être répétée plus d'une fois, respectivement. L’utilisation d’accolades après les parenthèses est également acceptable.

4. Début et fin de ligne

Il est souvent utile d'indiquer dans une expression régulière où une chaîne doit commencer et/ou se terminer. La première se fait en utilisant symbole de la casquette au début de l'expression, le second - en utilisant signe dollarà la fin. Exemples :

si ($text =~ /^*/ ) (
# texte commençant par un chiffre décimal
# approprié : 3, 801403, 6543bebebe
# ne convient pas : 0275, -123, abc11111
}

si ($texte =~ /^0x(1,8)$/ ) (
# nombre hexadécimal en notation C
# approprié : 0x5f3759df, 0xDEADBEEF
# ne convient pas : 0x1234xxx, xxx0x5678, xxx0x9ABCxxx
}

Pas difficile, non ? Veuillez noter que lors de la vérification des champs de formulaire Web, des arguments de fonction avant de les remplacer dans une requête SQL, etc. Nécessairement devrait être vérifié tous chaîne, comme dans la dernière expression régulière.

Note: Si quelqu'un est intéressé par ce que sont ces "nombres magiques" 0x5f3759df et 0xDEADBEEF, veuillez vous référer à Wikipedia.

5. Caractères spéciaux

En plus des caractères spéciaux mentionnés ci-dessus, il convient également de noter particulièrement indiquer. Elle veut dire n'importe lequel caractère autre que la nouvelle ligne. Exemple d'utilisation :

if (my ($name ) = $arg =~ /^--name=(.+)$/ ) (
imprimer "Bonjour, $name ! \n";
}

Par défaut, les expressions régulières produisent ce qu'on appelle analyse gourmande. En d’autres termes, des correspondances de longueur maximale sont recherchées. Lorsque nous utilisons un point, cela peut poser des problèmes. Par exemple, nous devons extraire du texte de centaines de pages HTML avec approximativement le contenu suivant :

<durée > Texte<em > texte</em> texte</envergure> Source : http://site/</envergure>

Le code suivant ne retournera pas ce que nous souhaitons :

# l'expression régulière contient une barre oblique, donc
# je dois utiliser un autre délimiteur à la place
(.*)#;
imprimer $texte ;
# imprimera la correspondance la plus longue :
#Texte texte texteSource : http://site/

Voici ce qui se passe si vous désactivez l'analyse gourmande (notez le point d'interrogation) :

mon ($text ) = $data =~ m # (.*?)#;
imprimer $texte ;
# imprimera la première correspondance :
#Texte texte texte

Oui, les lignes suivantes font la même chose :

# entrée régulière...
$texte =~ /({4})-({2})-({2})/ ;
# n'est en fait qu'un raccourci pour l'opérateur m//
$texte =~ m/((4))-((2))-((2))/;
# au lieu de la barre oblique, vous pouvez utiliser différentes parenthèses :
$text =~ m ( ([ 0 - 9 ] ( 4 ) ) - ( [ 0 - 9 ] ( 2 ) ) - ( [ 0 - 9 ] ( 2 ) ) ;
$texte =~ m< ([ 0 - 9 ] { 4 } ) - ([ 0 - 9 ] { 2 } ) - ([ 0 - 9 ] { 2 } ) >;
$text =~ m [ ([ 0 - 9 ] ( 4 ) ) - ( [ 0 - 9 ] ( 2 ) ) - ( [ 0 - 9 ] ( 2 ) ) ] ;
$text =~ m (([ 0 - 9 ] ( 4 ) ) - ( [ 0 - 9 ] ( 2 ) ) - ( [ 0 - 9 ] ( 2 ) ) ;
# ou même des symboles comme celui-ci :
$texte =~ m ! ([ 0 - 9 ] ( 4 ) ) - ( [ 0 - 9 ] ( 2 ) ) - ( [ 0 - 9 ] ( 2 ) ) !;
$texte =~ m | ([ 0 - 9 ] ( 4 ) ) - ( [ 0 - 9 ] ( 2 ) ) - ( [ 0 - 9 ] ( 2 ) ) |;
$texte =~ m #({4})-({2})-({2})#;
# ainsi que majuscule, guillemets, deux-points, virgule, point, ...

Pourquoi fallait-il autant de façons d’écrire des expressions régulières ? Imaginez que l'expression contienne des barres obliques, des points, des virgules et d'autres symboles, mais ne contient pas de point d'exclamation. Ensuite, évidemment, nous ne pouvons pas utiliser de barres obliques, de points, etc. pour indiquer le début et la fin d’une expression régulière, mais nous pouvons utiliser un point d’exclamation.

Souvent, dans les expressions régulières, vous devez utiliser barre oblique inverse. Placé avant un point, une parenthèse, un plus, une majuscule et d'autres symboles, cela signifie « le symbole suivant signifie exactement le symbole, et pas autre chose." Par exemple, voici comment déterminer une extension de fichier par son nom :

# point d'échappement avec barre oblique inverse
# signifie un point, pas "n'importe quel caractère"
mon ($ext ) = $fname =~ /\.(+)$/ ;
imprimer "nom du fichier : $fname, extension : $ext\n ";

De plus, la barre oblique inverse est utilisée dans la notation suivante :

  • \t— désigne un caractère de tabulation ( t ab)
  • \r Et \n- les caractères de retour chariot ( r retour) et nouvelle ligne ( n nouvelle ligne)
  • \xNN— correspond à un caractère avec le code ASCII NN, par exemple \x41 correspond à la lettre majuscule A de l'alphabet latin
  • \s- correspond à un espace ( s rythme), tabulation, nouvelle ligne ou retour chariot
  • \d- signifie n'importe quel nombre ( d igit), ou plus précisément, ce qui est considéré comme un nombre en Unicode (voir slide numéro 102 dans cette présentation)
  • \w- désigne le soi-disant « mot » ( w ord), analogique

Dans les trois dernières expressions, écrire la lettre en majuscule signifie la négation. Par exemple, \D correspond à l'expression [^0-9] , \W- expression [^0-9a-zA-Z_], UN \S- tout caractère « non-espace ».

Toutes ces expressions de « lettre » peuvent être utilisées entre crochets. Par exemple, l'expression tout à fait équivalent .

Les expressions méritent une attention particulière \b Et \B, signifiant la limite d'un mot (dans le même sens de « mot » que dans le cas de \w) et l'absence de limite de mot, respectivement. Par exemple, l'expression perl\b correspond à la chaîne "perl Rulez!", mais ne correspond pas à "perlmonk". Avec expression perl\B tout est exactement le contraire. J'espère que l'idée est claire.

Et encore un exemple :

# divise le nom complet du fichier en chemin et nom
mon ($path , $fname ) = $full_name =~ /^(.*)\/([^\/]+)$/ ;

Il illustre l'utilisation de la barre oblique inverse pour échapper un caractère utilisé pour désigner les limites d'une expression régulière. Dans cet exemple, il s'agit d'une barre oblique.

6. Modificateurs

Le comportement des expressions régulières peut être modifié à l'aide de modificateurs. Par exemple, comme vous l'avez peut-être déjà remarqué, la correspondance d'une chaîne avec une expression régulière est vérifiée en tenant compte de la casse. Vous pouvez modifier ce comportement en utilisant le modificateur # (.*?)#g;
# soyez prudent lorsque vous utilisez /g dans un contexte scalaire
# détails ici : http://koorchik.blogspot.com/2011/07/perl-5.html
imprimer "$_ \n" pour (@words) ;

Comme indiqué ci-dessus, un point désigne n'importe quel caractère sauf le caractère de nouvelle ligne. Vous pouvez modifier ce comportement à l'aide d'un modificateur /s:

# extraire le contenu de l'article du fichier HTML,
# qui peut contenir plus d'une ou deux lignes
mon ($article) = $html =~ m #

(.*?)
# ;

À propos, si dans une expression régulière vous devez indiquer « n'importe quel caractère » sans utiliser de modificateur /s, utilisez l'expression [\d\D]. Cela signifie « tout caractère qui est un chiffre ou n’est pas un chiffre », c’est-à-dire n’importe quel caractère.

Enfin, rien ne vous empêche d’utiliser plusieurs modificateurs en même temps :

# extraire tout ce qui est en gras du fichier HTML
mes @words = $html =~ m # (.*?)#gi;
# fonctionnera pour , ou même

Ajout: Un autre modificateur utile est /o. Cela signifie « compiler l’expression régulière une seule fois ». DANS quelques Dans certains cas, ce modificateur peut accélérer considérablement le script. Cependant, je ne suis pas sûr qu'il soit pris en charge ailleurs qu'en Perl. Merci pour le conseil camarade



Des questions ?

Signaler une faute de frappe

Texte qui sera envoyé à nos rédacteurs :