Englishfrançaisespagnol

Icône de favori OnWorks

perlretut - En ligne dans le Cloud

Exécutez perlretut dans le fournisseur d'hébergement gratuit OnWorks sur Ubuntu Online, Fedora Online, l'émulateur en ligne Windows ou l'émulateur en ligne MAC OS

Il s'agit de la commande perlretut qui peut être exécutée dans le fournisseur d'hébergement gratuit OnWorks en utilisant l'un de nos multiples postes de travail en ligne gratuits tels que Ubuntu Online, Fedora Online, l'émulateur en ligne Windows ou l'émulateur en ligne MAC OS

PROGRAMME:

Nom


perlretut - Tutoriel sur les expressions régulières Perl

DESCRIPTION


Cette page fournit un didacticiel de base sur la compréhension, la création et l'utilisation
expressions en Perl. Il sert de complément à la page de référence régulièrement
expressions perlières. Les expressions régulières font partie intégrante des "m//", "s///", "qr//"
et les opérateurs "split" et donc ce tutoriel chevauche également "Regexp Quote-Like
Operators" dans perlop et "split" dans perlfunc.

Perl est largement reconnu pour son excellence dans le traitement de texte, et les expressions régulières en font partie.
des grands facteurs derrière cette renommée. Les expressions régulières Perl affichent une efficacité et
flexibilité inconnue dans la plupart des autres langages informatiques. Maîtriser même les bases de
les expressions régulières vous permettront de manipuler du texte avec une facilité surprenante.

Qu'est-ce qu'une expression régulière ? Une expression régulière est simplement une chaîne qui décrit un
modèle. Les motifs sont d'usage courant de nos jours; les exemples sont les modèles tapés dans un
moteur de recherche pour trouver des pages Web et les modèles utilisés pour répertorier les fichiers dans un répertoire, par exemple,
"ls *.txt" ou "dir *.*". En Perl, les modèles décrits par les expressions régulières sont utilisés
pour rechercher des chaînes, extraire les parties de chaînes souhaitées et pour effectuer une recherche et un remplacement
fonctionnement sans maintenance

Les expressions régulières ont la réputation imméritée d'être abstraites et difficiles à
comprendre. Les expressions régulières sont construites à l'aide de concepts simples comme les conditions
et des boucles et ne sont pas plus difficiles à comprendre que les conditions "if" correspondantes
et des boucles "while" dans le langage Perl lui-même. En fait, le principal défi de l'apprentissage
les expressions régulières ne font que s'habituer à la notation laconique utilisée pour exprimer ces
concepts

Ce didacticiel aplatit la courbe d'apprentissage en discutant des concepts d'expression régulière, ainsi que
avec leur notation, un à la fois et avec de nombreux exemples. La première partie du tutoriel
passera des recherches de mots les plus simples aux concepts de base des expressions régulières.
Si vous maîtrisez la première partie, vous aurez tous les outils nécessaires pour résoudre environ 98% des
vos besoins. La deuxième partie du didacticiel s'adresse à ceux qui maîtrisent les bases et
faim pour plus d'outils électriques. Il traite des opérateurs d'expressions régulières les plus avancés
et présente les dernières innovations de pointe.

Remarque : pour gagner du temps, « expression régulière » est souvent abrégée en regexp ou regex.
Regexp est une abréviation plus naturelle que regex, mais est plus difficile à prononcer. Le Perl
la documentation du pod est répartie de manière égale entre regexp et regex ; en Perl, il y a plus d'une façon
pour l'abréger. Nous utiliserons regexp dans ce tutoriel.

Nouveau dans la v5.22, "use re 'strict'" applique des règles plus strictes qu'autrement lors de la compilation
modèles d'expressions régulières. Il peut trouver des choses qui, bien que légales, peuvent ne pas être ce que vous
prévu.

Partie 1: La bases


Simple mot assorti
L'expression rationnelle la plus simple est simplement un mot, ou plus généralement, une chaîne de caractères. Une expression régulière
composé d'un mot correspond à toute chaîne contenant ce mot :

"Bonjour le monde" =~ /Monde/; # allumettes

De quoi parle cette déclaration Perl ? "Hello World" est une simple chaîne entre guillemets.
"World" est l'expression régulière et le "//" englobant "/World/" indique à Perl de rechercher un
chaîne pour une correspondance. L'opérateur "=~" associe la chaîne à la correspondance d'expression régulière et
produit une valeur vraie si l'expression rationnelle correspond, ou fausse si l'expression rationnelle ne correspond pas. Dans notre
cas, "World" correspond au deuxième mot dans "Hello World", donc l'expression est vraie.
Des expressions comme celle-ci sont utiles au conditionnel :

if ("Bonjour le monde" =~ /Monde/) {
print "Cela correspond\n" ;
}
else {
print "Cela ne correspond pas\n" ;
}

Il existe des variations utiles sur ce thème. Le sens du match peut être inversé en
en utilisant l'opérateur "!~":

if ("Bonjour le monde" !~ /Monde/) {
print "Cela ne correspond pas\n" ;
}
else {
print "Cela correspond\n" ;
}

La chaîne littérale dans l'expression rationnelle peut être remplacée par une variable :

$salutation = "Monde" ;
if ("Bonjour tout le monde" =~ /$salutation/) {
print "Cela correspond\n" ;
}
else {
print "Cela ne correspond pas\n" ;
}

Si vous faites une correspondance avec la variable par défaut spéciale $_, la partie "$_ =~" peut être
omis:

$_ = "Bonjour tout le monde" ;
si (/Monde/) {
print "Cela correspond\n" ;
}
else {
print "Cela ne correspond pas\n" ;
}

Et enfin, les délimiteurs par défaut "//" pour une correspondance peuvent être changés en arbitraires
délimiteurs en mettant un « m » devant :

"Bonjour tout le monde" =~ m!Monde!; # correspondance, délimitée par '!'
"Bonjour le monde" =~ m{Monde} ; # correspondance, notez la correspondance '{}'
"/usr/bin/perl" =~ m"/perl"; # correspond après '/ usr / bin',
# '/' devient un caractère ordinaire

"/World/", "m!World!" et "m{World}" représentent tous la même chose. Quand, par exemple, la citation
(""") est utilisé comme délimiteur, la barre oblique '/' devient un caractère ordinaire et peut
être utilisé dans cette expression régulière sans problème.

Considérons comment différentes expressions régulières correspondraient à "Hello World":

"Bonjour tout le monde" =~ /monde/; # ne correspond pas
"Bonjour tout le monde" =~ /o W/; # allumettes
"Bonjour tout le monde" =~ /oW/; # ne correspond pas
"Bonjour le monde" =~ /Monde /; # ne correspond pas

La première expression régulière "world" ne correspond pas car les expressions régulières sont sensibles à la casse. La deuxième
regexp correspond car la sous-chaîne 'o W' apparaît dans la chaîne "Hello World". L'espace
le caractère ' ' est traité comme n'importe quel autre caractère dans une expression rationnelle et doit correspondre dans
ce cas. L'absence de caractère espace est la raison pour laquelle la troisième expression rationnelle 'oW' ne fonctionne pas
rencontre. La quatrième expression rationnelle 'World' ne correspond pas car il y a un espace à la fin de
l'expression rationnelle, mais pas à la fin de la chaîne. La leçon ici est que les expressions régulières doivent correspondre
une partie de la chaîne exactement pour que l'énoncé soit vrai.

Si une expression rationnelle correspond à plus d'un endroit dans la chaîne, Perl correspondra toujours à la
point le plus tôt possible dans la chaîne :

"Bonjour tout le monde" =~ /o/; # correspond à 'o' dans 'Bonjour'
"Ce chapeau est rouge" =~ /hat/; # correspond à « chapeau » dans « Ça »

En ce qui concerne la correspondance des caractères, il y a quelques points supplémentaires que vous devez savoir.
Tout d'abord, tous les caractères ne peuvent pas être utilisés « tels quels » dans un match. Certains personnages, appelés
métacaractères, sont réservés à une utilisation dans la notation regexp. Les métacaractères sont

{}[]()^$.|*+?\

La signification de chacun d'entre eux sera expliquée dans le reste du didacticiel, mais pour
maintenant, il est seulement important de savoir qu'un métacaractère peut être apparié en mettant un
barre oblique inverse avant :

"2+2=4" =~ /2+2/; # ne correspond pas, + est un métacaractère
"2+2=4" =~ /2\+2/; # correspond, \+ est traité comme un + ordinaire
"L'intervalle est [0,1)." =~ /[0,1)./ # est une erreur de syntaxe !
"L'intervalle est [0,1)." =~ /\[0,1\)\./ # correspond
"# !/usr/bin/perl" =~ /#!\/ usr\/ bin\/perl/; # allumettes

Dans la dernière expression rationnelle, la barre oblique '/' est également antislash, car elle est utilisée pour
délimiter l'expression rationnelle. Cela peut cependant conduire au LTS (syndrome du cure-dent penché), et il est
souvent plus lisible pour changer les délimiteurs.

"# !/usr/bin/perl" =~ m!#\!/usr/bin/perl!; # plus facile à lire

La barre oblique inverse '\' est elle-même un méta-caractère et doit être précédée d'une barre oblique inverse :

'C:\WIN32' =~ /C:\\WIN/; # allumettes

En plus des métacaractères, il existe des caractères ASCII qui n'ont pas
équivalents de caractères imprimables et sont plutôt représentés par échapper séquences. Commun
les exemples sont "\t" pour une tabulation, "\n" pour une nouvelle ligne, "\r" pour un retour chariot et "\a" pour un
cloche (ou alerte). Si votre chaîne est mieux considérée comme une séquence d'octets arbitraires,
la séquence d'échappement octale, par exemple, "\033", ou la séquence d'échappement hexadécimale, par exemple, "\x1B" peut
être une représentation plus naturelle de vos octets. Voici quelques exemples d'évasions :

"1000\t2000" =~ m(0\t2) # correspondances
"1000\n2000" =~ /0\n20/ # correspondances
"1000\t2000" =~ /\000\t2/ # ne correspond pas, "0" ne "\000"
"cat" =~ /\o{143}\x61\x74/ # correspond en ASCII, mais d'une manière étrange
# épeler chat

Si vous connaissez Perl depuis un certain temps, toutes ces discussions sur les séquences d'échappement peuvent vous sembler familières.
Des séquences d'échappement similaires sont utilisées dans les chaînes entre guillemets et en fait les expressions rationnelles en Perl
sont principalement traitées comme des chaînes entre guillemets. Cela signifie que les variables peuvent être utilisées dans
les expressions régulières aussi. Tout comme les chaînes entre guillemets, les valeurs des variables dans le
regexp sera remplacé avant que l'expression rationnelle ne soit évaluée à des fins de correspondance. Alors on
avoir:

$foo = 'maison';
'chat domestique' =~ /$foo/; # allumettes
'chalet' =~ /cat$foo/; # allumettes
'chat domestique' =~ /${foo}chat/; # allumettes

Jusqu'ici tout va bien. Avec les connaissances ci-dessus, vous pouvez déjà effectuer des recherches avec juste
à propos de n'importe quelle expression rationnelle de chaîne littérale que vous pouvez imaginer. Voici une très simple émulation de la
Programme grep Unix :

% chat > ​​simple_grep
#!/usr/bin/perl
$regexp = décalage ;
tandis que (<>) {
imprimer si /$regexp/;
}
^D

% chmod +x simple_grep

% simple_grep abba /usr/dict/words
Babbage
chou
choux
sabbat
Sabbat
Sabbats
sabbatique
fourreau
fourreaux

Ce programme est facile à comprendre. "# !/usr/bin/perl" est le moyen standard d'invoquer un
programme perl depuis le shell. "$ regexp = shift ;" enregistre le premier argument de la ligne de commande sous
l'expression rationnelle à utiliser, laissant le reste des arguments de la ligne de commande à traiter comme
des dossiers. "while (<>)" boucle sur toutes les lignes de tous les fichiers. Pour chaque ligne,
"print if /$regexp/;" imprime la ligne si l'expression rationnelle correspond à la ligne. Dans cette ligne, les deux
"print" et "/$regexp/" utilisent implicitement la variable $_ par défaut.

Avec toutes les expressions rationnelles ci-dessus, si l'expression rationnelle correspondait n'importe où dans la chaîne, c'était
considéré comme un match. Parfois, cependant, nous aimerions préciser dans la chaîne le
regexp devrait essayer de correspondre. Pour ce faire, nous utiliserions le ancre métacaractères "^" et
"$". L'ancre "^" signifie match au début de la chaîne et l'ancre "$" signifie
match à la fin de la chaîne, ou avant une nouvelle ligne à la fin de la chaîne. Voici comment
ils sont utilisés :

"femme de ménage" =~ /gardien/; # allumettes
"femme de ménage" =~ /^gardien/; # ne correspond pas
"femme de ménage" =~ /keeper$/; # allumettes
"femme de ménage\n" =~ /keeper$/; # allumettes

La deuxième expression rationnelle ne correspond pas car "^" contraint "keeper" à correspondre uniquement à la
début de la chaîne, mais "femme de ménage" a le gardien commençant au milieu. Le troisième
regexp correspond, car le "$" contraint "keeper" à correspondre uniquement à la fin du
chaîne.

Lorsque "^" et "$" sont utilisés en même temps, l'expression rationnelle doit correspondre à la fois au
le début et la fin de la chaîne, c'est-à-dire que l'expression rationnelle correspond à la chaîne entière. Envisager

"gardien" =~ /^keep$/; # ne correspond pas
"keeper" =~ /^keeper$/; # allumettes
"" =~ /^$/; # ^$ correspond à une chaîne vide

La première expression rationnelle ne correspond pas car la chaîne contient plus que "keep". Depuis le
la deuxième expression rationnelle est exactement la chaîne, elle correspond. Utiliser à la fois "^" et "$" dans une expression rationnelle
force la chaîne complète à correspondre, ce qui vous donne un contrôle total sur les chaînes
correspondent et qui ne le font pas. Supposons que vous recherchiez un gars nommé bert, dans une chaîne
par lui-même:

"dogbert" =~ /bert/; # correspond, mais pas ce que vous voulez

"dilbert" =~ /^bert/; # ne correspond pas, mais ..
"bertram" =~ /^bert/; # correspondance, donc toujours pas assez bon

"bertram" =~ /^bert$/; # ne correspond pas, bien
"dilbert" =~ /^bert$/; # ne correspond pas, bien
"bert" =~ /^bert$/; # correspondance, parfait

Bien entendu, dans le cas d'une chaîne littérale, on pourrait tout aussi bien utiliser la chaîne
comparaison "$string eq 'bert'" et ce serait plus efficace. L'expression régulière "^...$"
devient vraiment utile lorsque nous ajoutons les outils d'expression régulière plus puissants ci-dessous.

En utilisant caractère les classes
Bien que l'on puisse déjà faire pas mal de choses avec les expressions rationnelles de chaîne littérale ci-dessus, nous n'avons
gratté la surface de la technologie d'expression régulière. Dans cette section et les suivantes
nous introduirons des concepts d'expression régulière (et les notations de métacaractères associées) qui permettront
une expression rationnelle pour représenter non seulement une séquence de caractères unique, mais un la totalité classe d'eux.

L'un de ces concepts est celui d'un caractère classe. Une classe de caractères permet un ensemble de
caractères, plutôt qu'un seul caractère, pour correspondre à un point particulier d'un
expression rationnelle. Vous pouvez définir vos propres classes de personnages personnalisées. Ceux-ci sont indiqués par des parenthèses
"[...]", avec le jeu de caractères à faire éventuellement correspondre à l'intérieur. Voilà quelque
exemples:

/chat/; # correspond à 'chat'
/[bcr]à/; # correspond à 'bat, 'cat' ou 'rat'
/article[0123456789]/; # correspond à 'item0' ou ... ou 'item9'
"abc" =~ /[cab]/; # correspond à 'a'

Dans la dernière instruction, même si 'c' est le premier caractère de la classe, 'a' correspond
car la position du premier caractère dans la chaîne est le point le plus ancien auquel le
regexp peut correspondre.

/[yY][eE][sS]/; # correspond à 'oui' sans tenir compte de la casse
# 'oui', 'Oui', 'OUI', etc.

Cette expression rationnelle affiche une tâche courante : effectuer une correspondance insensible à la casse. Perl fournit un moyen
d'éviter toutes ces parenthèses en ajoutant simplement un "i" à la fin du match. Puis
"/[yY][eE][sS]/;" peut être réécrit comme "/yes/i;". Le 'i' signifie insensible à la casse et
est un exemple de modificateur de l'opération d'appariement. Nous rencontrerons d'autres modificateurs plus tard
dans le tutoriel.

Nous avons vu dans la section ci-dessus qu'il y avait des caractères ordinaires, qui représentaient
eux-mêmes, et les caractères spéciaux, qui nécessitaient une barre oblique inverse "\" pour se représenter.
La même chose est vraie dans une classe de caractères, mais les ensembles de caractères ordinaires et spéciaux
à l'intérieur d'une classe de caractères sont différents de ceux à l'extérieur d'une classe de caractères. Le spécial
les caractères d'une classe de caractères sont "-]\^$" (et le délimiteur de motif, quel qu'il soit).
"]" est spécial car il indique la fin d'une classe de caractères. "$" est spécial car il
désigne une variable scalaire. "\" est spécial car il est utilisé dans les séquences d'échappement, juste
comme ci-dessus. Voici comment sont traités les caractères spéciaux "]$\" :

/[\]c]def/; # correspond à ']def' ou 'cdef'
$x = 'bcr';
/[$x]à/; # correspond à 'bat', 'cat' ou 'rat'
/[\$x]à/; # correspond à '$at' ou 'xat'
/[\\$x]à/; # correspond à '\at', 'bat, 'cat' ou 'rat'

Les deux derniers sont un peu délicats. Dans "[\$x]", la barre oblique inverse protège le signe dollar, donc
la classe de caractères a deux membres "$" et "x". Dans "[\\$x]", la barre oblique inverse est protégée,
donc $x est traité comme une variable et remplacé par des guillemets doubles.

Le caractère spécial « - » agit comme un opérateur de plage dans les classes de caractères, de sorte qu'un
un ensemble contigu de caractères peut être écrit sous forme de plage. Avec des gammes, le lourd
"[0123456789]" et "[abc...xyz]" deviennent les sveltes "[0-9]" et "[az]". Quelques exemples sont

/item[0-9]/; # correspond à 'item0' ou ... ou 'item9'
/[0-9bx-z]aa/; # correspond à '0aa', ..., '9aa',
# 'baa', 'xaa', 'yaa' ou 'zaa'
/[0-9a-fA-F]/; # correspond à un chiffre hexadécimal
/[0-9a-zA-Z_]/; # correspond à un caractère "mot",
# comme ceux d'un nom de variable Perl

Si '-' est le premier ou le dernier caractère d'une classe de caractères, il est traité comme un
personnage; "[-ab]", "[ab-]" ​​et "[a\-b]" sont tous équivalents.

Le caractère spécial "^" en première position d'une classe de caractères désigne un annulé
caractère classe, qui correspond à n'importe quel caractère sauf ceux entre parenthèses. Les deux et
"[^...]" doit correspondre à un caractère, sinon la correspondance échoue. Puis

/[^a]à/; # ne correspond pas à 'aat' ou 'at', mais correspond
# tous les autres 'bat', 'cat, '0at', '%at', etc.
/[^0-9]/; # correspond à un caractère non numérique
/[a^]à/; # correspond à 'aat' ou '^at' ; ici '^' est ordinaire

Maintenant, même "[0-9]" peut être gênant d'écrire plusieurs fois, donc dans l'intérêt d'économiser
frappes et rendant les expressions régulières plus lisibles, Perl a plusieurs abréviations pour
classes de caractères, comme indiqué ci-dessous. Depuis l'introduction d'Unicode, à moins que le "//a"
modificateur est en vigueur, ces classes de caractères correspondent à plus que quelques caractères dans
la gamme ASCII.

· \d correspond à un chiffre, pas seulement [0-9] mais aussi des chiffres de scripts non romains

· \s correspond à un caractère d'espacement, l'ensemble [\ \t\r\n\f] et autres

· \w correspond à un caractère de mot (alphanumérique ou _), pas seulement [0-9a-zA-Z_] mais aussi des chiffres
et caractères de scripts non romains

· \D est un \d nié ; il représente tout autre caractère qu'un chiffre, ou [^\d]

· \S est un \s nié ; il représente n'importe quel caractère non blanc [^\s]

· \W est un \w nié ; il représente tout caractère autre qu'un mot [^\w]

· La période '.' correspond à n'importe quel caractère sauf "\n" (sauf si le modificateur "//s" est en vigueur,
comme expliqué ci-dessous).

· \N, comme le point, correspond à n'importe quel caractère sauf "\n", mais il le fait indépendamment de
si le modificateur "//s" est en vigueur.

Le modificateur "//a", disponible à partir de Perl 5.14, est utilisé pour restreindre les correspondances de
\d, \s et \w uniquement à ceux de la plage ASCII. Il est utile de garder votre programme de
être inutilement exposé à l'Unicode complet (et aux considérations de sécurité qui l'accompagnent)
quand tout ce que vous voulez est de traiter un texte de type anglais. (Le "a" peut être doublé, "//aa", pour
fournir encore plus de restrictions, empêchant la correspondance insensible à la casse de l'ASCII avec non-
caractères ASCII ; sinon, un « signe Kelvin » Unicode correspondrait sans casse à un « k » ou « K ».)

Les abréviations "\d\s\w\D\S\W" peuvent être utilisées à la fois à l'intérieur et à l'extérieur des crochets
classes de personnages. En voici quelques-uns en cours d'utilisation :

//d\d:\d\d:\d\d/; # correspond au format d'heure hh:mm:ss
/[\d\s]/; # correspond à n'importe quel chiffre ou caractère d'espace
/\w\W\w/; # correspond à un caractère de mot, suivi d'un
# caractère autre qu'un mot, suivi d'un caractère de mot
/..rt/; # correspond à deux caractères quelconques, suivis de 'rt'
/finir\./; # correspond à "fin".
/finir[.]/; # même chose, correspond à 'end'.

Parce qu'un point est un métacaractère, il doit être échappé pour correspondre à un
période. Parce que, par exemple, "\d" et "\w" sont des ensembles de caractères, il est incorrect de
pensez à "[^\d\w]" comme "[\D\W]" ; en fait "[^\d\w]" est le même que "[^\w]", qui est le
identique à "[\W]". Pensez aux lois de DeMorgan.

En réalité, le point et les abréviations "\d\s\w\D\S\W" sont eux-mêmes des types de
classes de caractères, donc celles entourées de crochets ne sont qu'un type de caractère
classer. Lorsque nous devons faire une distinction, nous les appelons "caractères entre crochets
Des classes."

Une ancre utile dans les expressions régulières de base est le mot ancre "\b". Cela correspond à une limite
entre un caractère verbal et un caractère non verbal "\w\W" ou "\W\w" :

$x = "Le chat domestique associe la maison et le chat" ;
$x =~ /chat/; # correspond au chat dans 'housecat'
$x =~ /\bcat/; # correspond au chat dans 'catenates'
$x =~ /cat\b/; # correspond au chat dans 'housecat'
$x =~ /\bcat\b/; # correspond à 'cat' à la fin de la chaîne

Notez que dans le dernier exemple, la fin de la chaîne est considérée comme une limite de mot.

Pour le traitement du langage naturel (afin que, par exemple, les apostrophes soient incluses dans les mots),
utilisez à la place "\b{wb}"

"ne pas" =~ / .+ ? \b{wb} /x; # correspond à la chaîne entière

Vous pourriez vous demander pourquoi '.' correspond à tout sauf "\n" - pourquoi pas à tous les caractères ? La raison
est-ce que souvent on fait correspondre des lignes et aimerait ignorer le saut de ligne
personnages. Par exemple, alors que la chaîne "\n" représente une ligne, nous aimerions
pensez-y comme vide. Puis

"" =~ /^$/; # allumettes
"\n" =~ /^$/; # correspond, $ ancres avant "\n"

"" =~ /./; # ne correspond pas ; il a besoin d'un caractère
"" =~ /^.$/; # ne correspond pas ; il a besoin d'un caractère
"\n" =~ /^.$/; # ne correspond pas ; il a besoin d'un caractère autre que "\n"
"a" =~ /^.$/; # allumettes
"a\n" =~ /^.$/; # correspond, $ ancres avant "\n"

Ce comportement est pratique, car nous voulons généralement ignorer les nouvelles lignes lorsque nous comptons et
faire correspondre les caractères d'une ligne. Parfois, cependant, nous voulons garder une trace des nouvelles lignes. Nous
peut-être même que "^" et "$" s'ancrent au début et à la fin des lignes dans la chaîne,
plutôt que juste le début et la fin de la chaîne. Perl nous permet de choisir entre
en ignorant et en prêtant attention aux nouvelles lignes en utilisant les modificateurs "//s" et "//m". "//s"
et "//m" signifient une ligne et plusieurs lignes et déterminent si une chaîne doit
être traité comme une chaîne continue ou comme un ensemble de lignes. Les deux modificateurs affectent deux
aspects de la façon dont l'expression rationnelle est interprétée : 1) comment le '.' la classe de caractères est définie, et
2) où les ancres "^" et "$" peuvent correspondre. Voici les quatre possibles
combinaisons:

· aucun modificateur (//) : Comportement par défaut. '.' correspond à n'importe quel caractère sauf "\n". "^"
correspond uniquement au début de la chaîne et "$" correspond uniquement à la fin ou avant
une nouvelle ligne à la fin.

· s modificateur (//s) : Traitez la chaîne comme une seule longue ligne. '.' correspond à n'importe quel caractère, même
"\n". "^" correspond uniquement au début de la chaîne et "$" correspond uniquement à la fin
ou avant une nouvelle ligne à la fin.

· m modificateur (//m) : Traitez la chaîne comme un ensemble de plusieurs lignes. '.' correspond à n'importe quel caractère
sauf "\n". "^" et "$" peuvent correspondre au début ou à la fin de tout ligne au sein de la
chaîne.

· les deux modificateurs s et m (//sm) : traitent la chaîne comme une seule longue ligne, mais détectent plusieurs
lignes. '.' correspond à n'importe quel caractère, même "\n". "^" et "$", cependant, peuvent correspondre
au début ou à la fin de tout ligne dans la chaîne.

Voici des exemples de "//s" et "//m" en action :

$x = "Il était une fois une fille\nQui a programmé en Perl\n";

$x =~ /^Qui/; # ne correspond pas, "Who" pas au début de la chaîne
$x =~ /^Qui/s; # ne correspond pas, "Who" pas au début de la chaîne
$x =~ /^Qui/m; # correspond, "Qui" au début de la deuxième ligne
$x =~ /^Qui/sm; # correspond, "Qui" au début de la deuxième ligne

$x =~ /fille.Qui/; # ne correspond pas, "." ne correspond pas à "\n"
$x =~ /fille.Qui/s; # allumettes, "." correspond à "\n"
$x =~ /fille.Qui/m; # ne correspond pas, "." ne correspond pas à "\n"
$x =~ /fille.Qui/sm; # allumettes, "." correspond à "\n"

La plupart du temps, le comportement par défaut est ce qui est souhaité, mais "//s" et "//m" sont
parfois très utile. Si "//m" est utilisé, le début de la chaîne peut toujours être
correspond à "\A" et la fin de la chaîne peut toujours être associée aux ancres "\Z"
(correspond à la fois à la fin et à la nouvelle ligne avant, comme "$"), et "\z" (correspond uniquement à la fin) :

$x =~ /^Qui/m; # correspond, "Qui" au début de la deuxième ligne
$x =~ /\AHo/m; # ne correspond pas, "Who" n'est pas au début de la chaîne

$x =~ /fille$/m ; # correspondances, "fille" à la fin de la première ligne
$x =~ /fille\Z/m; # ne correspond pas, "girl" n'est pas à la fin de la chaîne

$x =~ /Perl\Z/m; # correspond, "Perl" est à la nouvelle ligne avant la fin
$x =~ /Perl\z/m; # ne correspond pas, "Perl" n'est pas à la fin de la chaîne

Nous savons maintenant comment créer des choix parmi les classes de caractères dans une regexp. Qu'en est-il de
choix parmi des mots ou des chaînes de caractères ? Ces choix sont décrits dans la section suivante.

Adaptir ceci. or qui
Parfois, nous aimerions que notre regexp puisse correspondre à différents mots possibles ou
chaînes de caractères. Ceci est accompli en utilisant le alternance métacaractère "|". À
match "dog" ou "cat", nous formons l'expression régulière "dog|cat". Comme auparavant, Perl essaiera de faire correspondre le
regexp le plus tôt possible dans la chaîne. A chaque position de caractère, Perl
essaiera d'abord de faire correspondre la première alternative, "chien". Si "chien" ne correspond pas, Perl
puis essayez l'alternative suivante, "chat". Si "cat" ne correspond pas non plus, alors la correspondance échoue
et Perl passe à la position suivante dans la chaîne. Quelques exemples:

"chats et chiens" =~ /chat|chien|oiseau/; # correspond à "chat"
"chats et chiens" =~ /chien|chat|oiseau/; # correspond à "chat"

Même si "dog" est la première alternative dans la deuxième regexp, "cat" est capable de correspondre
plus tôt dans la chaîne.

"chats" =~ /c|ca|chat|chats/; # correspond à "c"
"chats" =~ /chats|chat|ca|c/; # correspond à "chats"

Ici, toutes les alternatives correspondent à la première position de la chaîne, donc la première alternative est
celui qui correspond. Si certaines des alternatives sont des troncatures des autres, mettez la
les plus longs en premier pour leur donner une chance d'égaler.

"cab" =~ /a|b|c/ # correspond à "c"
# /a|b|c/ == /[abc]/

Le dernier exemple montre que les classes de caractères sont comme des alternances de caractères.
À une position de caractère donnée, la première alternative qui permet à l'expression rationnelle de correspondre à
réussir sera celui qui correspond.

regroupement des choses et Hiérarchique assorti
L'alternance permet à une expression rationnelle de choisir parmi des alternatives, mais en soi elle est
insatisfaisant. La raison en est que chaque alternative est une expression régulière entière, mais parfois nous voulons
alternatives pour juste une partie d'une expression rationnelle. Par exemple, supposons que nous voulions rechercher
chats domestiques ou femmes de ménage. L'expression régulière "housecat|housekeeper" fait l'affaire, mais est
inefficace car nous avons dû taper "maison" deux fois. Ce serait bien d'avoir des parties du
regexp soit constante, comme "house", et certaines parties ont des alternatives, comme "cat|keeper".

La regroupement les métacaractères "()" résolvent ce problème. Le regroupement permet aux parties d'une expression régulière de
être traité comme une seule unité. Les parties d'une expression rationnelle sont regroupées en les enfermant dans
parenthèses. Ainsi, nous pourrions résoudre le "housecat|housekeeper" en formant l'expression rationnelle comme
"maison(chat|gardien)". L'expression régulière "house(cat|keeper)" signifie correspondre à "house" suivi de
soit "chat" ou "gardien". Quelques autres exemples sont

/(a|b)b/; # correspond à 'ab' ou 'bb'
/(ac|b)b/; # correspond à 'acb' ou 'bb'
/(^a|b)c/; # correspond à 'ac' au début de la chaîne ou à 'bc' n'importe où
/(a|[bc])d/; # correspond à 'ad', 'bd' ou 'cd'

/maison(chat|)/; # correspond à 'housecat' ou 'house'
/maison(chat(s|)|)/; # correspond à 'housecats' ou 'housecat' ou
# 'loger'. Les groupes de notes peuvent être imbriqués.

/(19|20|)\d\d/; # correspond aux années 19xx, 20xx ou au problème de l'an 2, xx
"20" =~ /(19|20|)\d\d/; # correspond à l'alternative nulle '()\d\d',
# parce que '20\d\d' ne peut pas correspondre

Les alternances se comportent de la même manière dans les groupes qu'en dehors : à une position de chaîne donnée, le
L'alternative la plus à gauche qui permet à l'expression rationnelle de correspondre est prise. Ainsi, dans le dernier exemple à
la première position de chaîne, "20" correspond à la deuxième alternative, mais il ne reste plus rien
pour faire correspondre les deux chiffres suivants "\d\d". Perl passe donc à l'alternative suivante, qui
est l'alternative nulle et cela fonctionne, puisque "20" est deux chiffres.

Le processus consistant à essayer une alternative, à voir si elle correspond et à passer à la suivante
alternative, en remontant dans la chaîne d'où l'alternative précédente a été tentée,
si ce n'est pas le cas, est appelé retour en arrière. Le terme « retour en arrière » vient de l'idée que
faire correspondre une expression rationnelle est comme une promenade dans les bois. Faire correspondre avec succès une expression régulière est comme
arriver à destination. Il existe de nombreux départs de sentiers possibles, un pour chaque chaîne
position, et chacun est essayé dans l'ordre, de gauche à droite. De chaque départ de sentier, il peut y avoir
de nombreux chemins, dont certains vous y mènent et d'autres qui sont des impasses. Lorsque vous marchez
le long d'un sentier et dans une impasse, vous devez faire marche arrière le long du sentier jusqu'à un
pointez pour essayer un autre sentier. Si vous atteignez votre destination, vous vous arrêtez immédiatement et oubliez
d'essayer tous les autres sentiers. Vous êtes persévérant, et seulement si vous avez essayé tous les
sentiers de tous les points de départ et non arrivés à destination, déclarez-vous
échec. Pour être concret, voici une analyse étape par étape de ce que fait Perl lorsqu'il essaie
pour correspondre à l'expression régulière

"abcde" =~ /(abd|abc)(df|d|de)/;

0 Commencez par la première lettre de la chaîne 'a'.

1 Essayez la première alternative dans le premier groupe 'abd'.

2 Faites correspondre « a » suivi de « b ». Jusqu'ici tout va bien.

3 'd' dans l'expression rationnelle ne correspond pas à 'c' dans la chaîne - une impasse. Alors reviens deux
caractères et choisissez la deuxième alternative dans le premier groupe 'abc'.

4 Faites correspondre 'a' suivi de 'b' suivi de 'c'. Nous sommes sur une lancée et avons satisfait
premier groupe. Réglez $1 sur 'abc'.

5 Passez au deuxième groupe et choisissez la première alternative « df ».

6 Faites correspondre le 'd'.

7 'f' dans l'expression rationnelle ne correspond pas à 'e' dans la chaîne, donc une impasse. Revenir en arrière
caractère et choisissez la deuxième alternative dans le deuxième groupe 'd'.

8 matchs « d ». Le deuxième groupe est satisfait, alors définissez $2 sur 'd'.

9 Nous sommes à la fin de l'expression régulière, nous avons donc terminé ! Nous avons fait correspondre « abcd » sur le
chaîne "abcde".

Il y a deux ou trois choses à noter à propos de cette analyse. Premièrement, la troisième alternative dans
le deuxième groupe 'de' permet également un match, mais nous nous sommes arrêtés avant d'y arriver - à un moment donné
position du personnage, le plus à gauche gagne. Deuxièmement, nous avons pu obtenir un match au premier
position du caractère de la chaîne 'a'. S'il n'y a pas eu de matchs en première position,
Perl se déplacerait jusqu'à la position du deuxième caractère « b » et tenterait à nouveau la correspondance.
Ce n'est que lorsque tous les chemins possibles à toutes les positions de caractère possibles ont été épuisés que
Perl abandonne et déclare "$string =~ /(abd|abc)(df|d|de)/;" être faux.

Même avec tout ce travail, la correspondance d'expressions rationnelles est remarquablement rapide. Pour accélérer les choses,
Perl compile l'expression rationnelle en une séquence compacte d'opcodes qui peuvent souvent tenir dans un
cache du processeur. Lorsque le code est exécuté, ces opcodes peuvent alors s'exécuter à plein régime
et recherchez très rapidement.

Extraire allumettes
Les métacaractères de regroupement "()" remplissent également une autre fonction complètement différente : ils
permettre l'extraction des parties d'une chaîne qui correspondent. C'est très utile pour trouver
ce qui correspondait et pour le traitement de texte en général. Pour chaque groupement, la partie qui
correspond à l'intérieur va dans les variables spéciales $1, $2, etc. Elles peuvent être utilisées comme
variables ordinaires :

# extrait les heures, minutes, secondes
if ($time =~ /(\d\d):(\d\d):(\d\d)/) { # correspond au format hh:mm:ss
$heures = 1$;
$minutes = 2$;
$ secondes = 3 $ ;
}

Maintenant, nous savons que dans un contexte scalaire, "$time =~ /(\d\d):(\d\d):(\d\d)/" renvoie un vrai ou
fausse valeur. Dans le contexte de la liste, cependant, il renvoie la liste des valeurs correspondantes
"($1,$2,$3)". Nous pourrions donc écrire le code de manière plus compacte sous la forme

# extrait les heures, minutes, secondes
($heures, $minutes, $seconde) = ($time =~ /(\d\d):(\d\d):(\d\d)/);

Si les regroupements dans une expression rationnelle sont imbriqués, $1 obtient le groupe avec l'ouverture la plus à gauche
parenthèse, $2 la prochaine parenthèse ouvrante, etc. Voici une expression rationnelle avec des groupes imbriqués :

/(ab(cd|ef)((gi)|j))/ ;
1 2 34

Si cette expression rationnelle correspond, $1 contient une chaîne commençant par 'ab', $2 est soit défini sur 'cd'
ou 'ef', $3 est égal à 'gi' ou 'j', et $4 est soit mis à 'gi', tout comme $3, soit il
reste indéfini.

Pour plus de commodité, Perl définit $+ sur la chaîne détenue par le numéro le plus élevé $1, $2,... qui
a été affecté (et, quelque peu lié, $^N à la valeur du $1, $2,... le plus récemment
attribué; c'est-à-dire les $1, $2,... associés à la parenthèse fermante la plus à droite utilisée dans
le match).

Références arrière
Étroitement associées aux variables d'appariement $1, $2, ... sont les références en arrière "\g1",
"\g2",... Les backreferences sont simplement des variables de correspondance qui peuvent être utilisées à l'intérieur une expression rationnelle.
C'est une fonctionnalité vraiment sympa; ce qui correspond plus tard dans une expression rationnelle dépend de ce que
correspondait plus tôt dans l'expression régulière. Supposons que nous voulions rechercher des mots doublés dans un texte,
comme 'le le'. L'expression régulière suivante trouve tous les doubles de 3 lettres avec un espace entre les deux :

/\b(\w\w\w)\s\g1\b/ ;

Le regroupement attribue une valeur à \g1, de sorte que la même séquence de 3 lettres est utilisée pour les deux
des pièces.

Une tâche similaire consiste à trouver des mots composés de deux parties identiques :

% simple_grep '^(\w\w\w\w|\w\w\w|\w\w|\w)\g1$' /usr/dict/words
béribéri
bobo
noix de coco
maman
murmure
papa

L'expression rationnelle a un seul regroupement qui considère les combinaisons de 4 lettres, puis de 3 lettres
combinaisons, etc., et utilise "\g1" pour rechercher une répétition. Bien que $1 et "\g1" représentent
la même chose, il faut veiller à utiliser les variables appariées $1, $2,... uniquement au contrôle a
regexp et backreferences "\g1", "\g2",... uniquement à l'intérieur une expression régulière ; ne pas le faire peut conduire à
résultats surprenants et insatisfaisants.

Relatif références en arrière
Compter les parenthèses ouvrantes pour obtenir le nombre correct pour une référence arrière est une erreur-
sujettes dès qu'il y a plus d'un groupe de capture. Une technique plus pratique
est devenu disponible avec Perl 5.10 : références arrière relatives. Pour se référer immédiatement
le groupe de capture précédent un peut maintenant écrire "\g{-1}", le suivant mais le dernier est disponible via
"\g{-2}", et ainsi de suite.

Une autre bonne raison en plus de la lisibilité et de la maintenabilité pour utiliser
Les références arrières sont illustrées par l'exemple suivant, où un modèle simple pour
correspondant à des chaînes particulières est utilisé :

$a99a = '([az])(\d)\g2\g1'; # correspond à a11a, g22g, x33x, etc.

Maintenant que nous avons ce modèle stocké sous forme de chaîne pratique, nous pourrions être tentés de l'utiliser comme
une partie d'un autre modèle:

$line = "code=e99e" ;
if ($line =~ /^(\w+)=$a99a$/){ # comportement inattendu !
print "$1 est valide\n" ;
} Else {
print "mauvaise ligne : '$line'\n" ;
}

Mais cela ne correspond pas, du moins pas comme on pourrait s'y attendre. Ce n'est qu'après avoir inséré le
interpolé $a99a et en regardant le texte complet résultant de l'expression rationnelle, il est évident que
les références arrière se sont retournées contre vous. La sous-expression "(\w+)" a arraché le numéro 1 et
rétrogradé les groupes de $a99a d'un rang. Ceci peut être évité en utilisant
références arrière :

$a99a = '([az])(\d)\g{-1}\g{-2}'; # sûr pour être interpolé

Nommé références en arrière
Perl 5.10 a également introduit des groupes de capture nommés et des références arrière nommées. Pour attacher un nom
à un groupe de capture, vous écrivez soit "(? ...)" ou "(?'nom'...)".
backreference peut alors être écrit comme "\g{name}". Il est permis de joindre le même
nom à plus d'un groupe, mais alors seul le plus à gauche de l'ensemble éponyme peut être
référencé. En dehors du modèle, un groupe de capture nommé est accessible via le "%+"
hacher.

En supposant que nous devons faire correspondre des dates de calendrier qui peuvent être données dans l'un des trois
formats aaaa-mm-jj, mm/jj/aaaa ou jj.mm.aaaa, nous pouvons écrire trois modèles appropriés où
nous utilisons 'd', 'm' et 'y' respectivement comme noms des groupes capturant les
composants d'une date. L'opération d'appariement combine les trois modèles comme alternatives :

$fmt1 = '(? \d\d\d\d)-(? \d\d)-(? \d\d)';
$fmt2 = '(? \d\d)/(? \d\d)/(? \d\d\d\d)';
$fmt3 = '(? \d\d)\.(? \d\d)\.(? \d\d\d\d)';
pour mon $d qw ( 2006/10/21 15.01.2007 10/31/2005 ){
si ( $d =~ m{$fmt1|$fmt2|$fmt3} ){
print "jour=$+{d} mois=$+{m} année=$+{y}\n" ;
}
}

Si l'une des alternatives correspond, le hachage "%+" doit contenir les trois valeurs-clés
paires.

Alternative capturer groupe numérotage
Une autre technique de numérotation des groupes de capture (également à partir de Perl 5.10) traite de la
problème de référence à des groupes au sein d'un ensemble d'alternatives. Considérez un modèle pour
correspondant à un moment de la journée, de style civil ou militaire :

si ( $heure =~ /(\d\d|\d):(\d\d)|(\d\d)(\d\d)/ ){
# heure et minute de traitement
}

Le traitement des résultats nécessite une instruction if supplémentaire pour déterminer si $1 et $2
ou 3 $ et 4 $ contiennent les goodies. Ce serait plus facile si nous pouvions utiliser les numéros de groupe 1 et 2
dans la deuxième alternative également, et c'est exactement ce que la construction entre parenthèses
"(?|...)", mis en place autour d'une alternative réalise. Voici une version étendue du précédent
modèle:

if($time =~ /(?|(\d\d|\d):(\d\d)|(\d\d)(\d\d))\s+([AZ][AZ][ AZ])/){
print "heure=$1 minute=$2 zone=$3\n" ;
}

Dans le groupe de numérotation alternative, les numéros de groupe commencent à la même position pour chaque
alternative. Après le groupe, la numérotation continue avec un supérieur au maximum atteint
à travers toutes les alternatives.

Position d'information
En plus de ce qui a été apparié, Perl fournit également les positions de ce qui a été apparié comme
contenu des tableaux "@-" et "@+". "$-[0]" est la position du début de l'ensemble
match et $+[0] est la position de la fin. De même, "$-[n]" est la position du
début de la correspondance $n et $+[n] est la position de la fin. Si $n n'est pas défini, il en va de même
"$-[n]" et $+[n]. Alors ce code

$x = "Mmm... beignet, pensa Homer" ;
$x =~ /^(Mmm|Yech)\.\.\.(beigne|pois)/; # allumettes
foreach $exp (1..$#-) {
print "Correspond à $exp : '${$exp}' à la position ($-[$exp],$+[$exp])\n" ;
}

impressions

Match 1 : 'Mmm' à la position (0,3)
Match 2: 'donut' à la position (6,11)

Même s'il n'y a pas de regroupements dans une expression rationnelle, il est toujours possible de savoir exactement quoi
correspond à une chaîne. Si vous les utilisez, Perl définira "$`" sur la partie de la chaîne avant
la correspondance, définira $& sur la partie de la chaîne qui correspondait et définira "$'" sur le
partie de la chaîne après le match. Un exemple:

$x = "le chat a attrapé la souris";
$x =~ /chat/; # $` = 'le ', $& = 'chat', $' = ' a attrapé la souris'
$x =~ /le/; # $` = '', $& = 'le', $' = ' le chat a attrapé la souris'

Dans la deuxième correspondance, "$`" est égal à '' car l'expression rationnelle correspond au premier caractère
position dans la chaîne et arrêté; il n'a jamais vu le second « le ».

Si votre code doit s'exécuter sur des versions de Perl antérieures à 5.20, il est intéressant de noter que
utiliser "$`" et "$'" ralentit un peu la correspondance des expressions régulières, tandis que $& le ralentit à un
dans une moindre mesure, car s'ils sont utilisés dans une expression rationnelle d'un programme, ils sont générés pour
tous expressions rationnelles dans le programme. Ainsi, si les performances brutes sont un objectif de votre application, elles
devrait être évité. Si vous devez extraire les sous-chaînes correspondantes, utilisez "@-" et "@+"
au lieu:

$` est le même que substr( $x, 0, $-[0] )
$& est le même que substr( $x, $-[0], $+[0]-$-[0] )
$' est le même que substr( $x, $+[0] )

Depuis Perl 5.10, les variables "${^PREMATCH}", "${^MATCH}" et "${^POSTMATCH}" peuvent être
utilisé. Ceux-ci ne sont définis que si le modificateur "/p" est présent. Par conséquent, ils ne
pénaliser le reste du programme. Dans Perl 5.20, "${^PREMATCH}", "${^MATCH}" et
"${^POSTMATCH}" sont disponibles que le "/p" ait été utilisé ou non (le modificateur est
ignoré), et "$`", "$'" et $& n'entraînent aucune différence de vitesse.

Non-capturant regroupements
Un groupe qui doit regrouper un ensemble d'alternatives peut être utile ou non en tant que
groupe de capture. Si ce n'est pas le cas, cela crée simplement un ajout superflu à l'ensemble des
valeurs de groupe de capture disponibles, à l'intérieur comme à l'extérieur de l'expression rationnelle. Non-capturant
les regroupements, notés "(?:regexp)", permettent toujours à l'expression rationnelle d'être traitée comme une seule unité,
mais n'établissez pas un groupe de capture en même temps. Capture et non capture
les regroupements sont autorisés à coexister dans la même expression rationnelle. Parce qu'il n'y a pas d'extraction,
les regroupements sans capture sont plus rapides que les regroupements avec capture. Les groupements non capturants sont
également pratique pour choisir exactement quelles parties d'une expression rationnelle doivent être extraites pour correspondre
variables:

# correspond à un nombre, $1-$4 sont définis, mais nous ne voulons que $1
/([+-]?\ *(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?)/ ;

# correspond à un nombre plus rapidement, seul 1 $ est défini
/([+-]?\ *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?)/ ;

# correspond à un nombre, obtient $1 = nombre entier, $2 = exposant
/([+-]?\ *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE]([+-]?\d+))?)/ ;

Les groupements non capturants sont également utiles pour supprimer les éléments nuisibles collectés à partir d'un
opération de fractionnement où les parenthèses sont requises pour une raison quelconque :

$x = '12aba34ba5';
@num = diviser /(a|b)+/, $x; # @num = ('12','a','34','a','5')
@num = split /(?:a|b)+/, $x; # @num = ('12','34','5')

Dans Perl 5.22 et versions ultérieures, tous les groupes d'une expression rationnelle peuvent être définis sur non-capturant en utilisant
le nouveau drapeau "/n":

"salut" =~ /(salut|salut)/n; # $1 n'est pas défini !

Voir "n" dans perlre pour plus d'informations.

Adaptir répétitions
Les exemples de la section précédente présentent une faiblesse gênante. Nous correspondions seulement
Mots de 3 lettres, ou morceaux de mots de 4 lettres ou moins. Nous aimerions pouvoir correspondre
des mots ou, plus généralement, des chaînes de n'importe quelle longueur, sans écrire d'alternatives fastidieuses
comme "\w\w\w\w|\w\w\w|\w\w|\w".

C'est exactement le problème que quantificateur les métacaractères "?", "*", "+" et "{}" étaient
créé pour. Ils nous permettent de délimiter le nombre de répétitions pour une partie d'une expression rationnelle que nous
considérer comme un match. Les quantificateurs sont placés immédiatement après le caractère, caractère
classe ou groupe que nous voulons spécifier. Ils ont les significations suivantes :

· "une?" signifie : correspond à 'a' 1 ou 0 fois

· « a* » signifie : correspond à « a » 0 fois ou plus, c'est-à-dire un nombre quelconque de fois

· « a+ » signifie : correspondre à « a » 1 ou plusieurs fois, c'est-à-dire au moins une fois

· "a{n,m}" signifie : correspondre au moins à "n" fois, mais pas plus de "m" fois.

· "a{n,}" signifie : correspond au moins à "n" ou plusieurs fois

· "a{n}" signifie : correspond exactement "n" fois

Voici quelques exemples:

/[az]+\s+\d*/; # correspond à un mot en minuscule, au moins un espace, et
# un nombre quelconque de chiffres
/(\w+)\s+\g1/; # correspond à des mots doublés de longueur arbitraire
/Oui je; # correspond à 'y', 'Y' ou à un 'oui' insensible à la casse
$année =~ /^\d{2,4}$/; # assurez-vous que l'année est au moins 2 mais pas plus
# de 4 chiffres
$année =~ /^\d{4}$|^\d{2}$/; # meilleure correspondance ; jeter les dates à 3 chiffres
$année =~ /^\d{2}(\d{2})?$/; # la même chose écrite différemment.
# Cependant, cela capture les deux derniers
# chiffres dans $1 et l'autre non.

% simple_grep '^(\w+)\g1$' /usr/dict/words # n'est-ce pas plus facile ?
béribéri
bobo
noix de coco
maman
murmure
papa

Pour tous ces quantificateurs, Perl essaiera de faire correspondre autant de chaîne que possible,
tout en permettant à l'expression régulière de réussir. Ainsi avec "/a?.../", Perl essaiera d'abord de
faire correspondre l'expression rationnelle avec le "a" présent ; si cela échoue, Perl essaiera de faire correspondre l'expression rationnelle
sans le "a" présent. Pour le quantificateur "*", on obtient :

$x = "le chat au chapeau";
$x =~ /^(.*)(chat)(.*)$/; # allumettes,
# $1 = 'le '
# $2 = 'chat'
# $3 = 'dans le chapeau'

C'est ce à quoi on pourrait s'attendre, le match trouve le seul "chat" dans la chaîne et se verrouille sur
ce. Considérez, cependant, cette expression rationnelle :

$x =~ /^(.*)(at)(.*)$/; # allumettes,
# $1 = 'le chat dans le h'
# $2 = 'à'
# $3 = '' (correspondance de 0 caractères)

On pourrait d'abord deviner que Perl trouverait le "at" dans "cat" et s'arrêterait là, mais que
ne donnerait pas la chaîne la plus longue possible au premier quantificateur ".*". Au lieu de cela, le
premier quantificateur ".*" saisit autant de chaîne que possible tout en ayant toujours le
correspondance d'expression régulière. Dans cet exemple, cela signifie avoir la séquence « à » avec le « à » final dans
la chaîne. L'autre principe important illustré ici est que, lorsqu'il y a deux ou
plus d'éléments dans une regexp, le le plus à gauche quantificateur, s'il y en a un, en prend autant
de la chaîne que possible, laissant le reste de l'expression rationnelle se battre pour les restes. Ainsi dans
notre exemple, le premier quantificateur ".*" saisit la majeure partie de la chaîne, tandis que le second
quantifier ".*" obtient la chaîne vide. Quantificateurs qui saisissent autant de chaîne que
possibles sont appelés maximale rencontre or avide quantificateurs.

Lorsqu'une expression rationnelle peut correspondre à une chaîne de plusieurs manières différentes, nous pouvons utiliser les principes
ci-dessus pour prédire de quelle manière l'expression rationnelle correspondra :

· Principe 0 : Prise dans son ensemble, toute expression rationnelle sera mise en correspondance le plus tôt possible
position dans la chaîne.

· Principe 1 : Dans une alternance "a|b|c...", l'alternative la plus à gauche qui permet une
match pour l'ensemble de l'expression régulière sera celui utilisé.

· Principe 2 : Les quantificateurs d'appariement maximaux "?", "*", "+" et "{n,m}" seront en
match général autant de la chaîne que possible tout en autorisant l'ensemble de l'expression rationnelle
correspondre.

· Principe 3 : S'il y a deux éléments ou plus dans une expression rationnelle, le plus à gauche
quantificateur, le cas échéant, correspondra à autant de chaîne que possible tout en permettant
l'ensemble de l'expression régulière pour correspondre. Le prochain quantificateur gourmand le plus à gauche, le cas échéant, essaiera de
correspondre autant que possible à la chaîne qui lui reste disponible, tout en
permettant à l'ensemble de l'expression régulière de correspondre. Et ainsi de suite, jusqu'à ce que tous les éléments regexp soient
satisfait.

Comme nous l'avons vu plus haut, le Principe 0 prévaut sur les autres. L'expression régulière sera mise en correspondance comme
le plus tôt possible, les autres principes déterminant comment l'expression rationnelle correspond à ce moment
première position du personnage.

Voici un exemple de ces principes en action :

$x = "La république de programmation de Perl";
$x =~ /^(.+)(e|r)(.*)$/; # allumettes,
# $1 = 'La république de programmation de Pe'
# $2 = 'r'
# $3 = 'l'

Cette expression rationnelle correspond à la première position de chaîne, « T ». On pourrait penser que "e", étant
le plus à gauche dans l'alternance, serait apparié, mais "r" produit la chaîne la plus longue dans le
premier quantificateur.

$x =~ /(m{1,2})(.*)$/; # allumettes,
# $1 = 'mm'
# $2 = 're république de Perl'

Ici, la première correspondance possible est au premier « m » dans « programmation ». "m{1,2}" est le
premier quantificateur, il doit donc correspondre à un "mm" maximal.

$x =~ /.*(m{1,2})(.*)$/; # allumettes,
# $1 = 'm'
# $2 = 're république de Perl'

Ici, l'expression rationnelle correspond au début de la chaîne. Le premier quantificateur ".*" saisit comme
autant que possible, en ne laissant qu'un seul « m » pour le deuxième quantificateur « m{1,2} ».

$x =~ /(.?)(m{1,2})(.*)$/; # allumettes,
# $1 = 'a'
# $2 = 'mm'
# $3 = 're république de Perl'

Ici, ".?" mange son caractère maximal à la première position possible dans la chaîne,
'a' dans "programming", laissant à "m{1,2}" la possibilité de faire correspondre les deux "m". Finalement,

"aXXXb" =~ /(X*)/; # correspond à $1 = ''

car il peut correspondre à zéro copie de 'X' au début de la chaîne. Si vous avez certainement
voulez faire correspondre au moins un « X », utilisez « X+ », et non « X* ».

Parfois, la cupidité n'est pas bonne. Parfois, nous aimerions que les quantificateurs correspondent à un minimal pièce
de ficelle, plutôt qu'un morceau maximal. À cette fin, Larry Wall a créé le minimal
rencontre or non gourmand quantificateurs "??", "*?", "+?" et "{}?". Ce sont les habituels
quantificateurs avec un "?" leur est annexé. Ils ont les significations suivantes :

· "une??" signifie : correspond à 'a' 0 ou 1 fois. Essayez 0 d'abord, puis 1.

· "une*?" signifie : correspond à 'a' 0 fois ou plus, c'est-à-dire n'importe quel nombre de fois, mais aussi peu de fois que
possible

· "un+?" signifie : correspondre à 'a' 1 ou plusieurs fois, c'est-à-dire au moins une fois, mais aussi peu de fois que
possible

· "a{n,m} ?" signifie : faire correspondre au moins "n" fois, pas plus de "m" fois, aussi peu de fois que
possible

· "un,}?" signifie : faire correspondre au moins « n » fois, mais aussi peu de fois que possible

· "un}?" signifie : correspond exactement "n" fois. Parce que nous faisons correspondre exactement "n" fois, "a{n} ?"
est équivalent à "a{n}" et est juste là pour la cohérence de la notation.

Regardons l'exemple ci-dessus, mais avec des quantificateurs minimes :

$x = "La république de programmation de Perl";
$x =~ /^(.+?)(e|r)(.*)$/; # allumettes,
# $1 = 'Je'
# $2 = 'e'
# $3 = ' programmation république de Perl'

La chaîne minimale qui permettra à la fois le début de la chaîne "^" et l'alternance de
match est "Th", avec l'alternance "e|r" correspondant à "e". Le deuxième quantificateur ".*" est
libre d'engloutir le reste de la ficelle.

$x =~ /(m{1,2}?)(.*?)$/; # allumettes,
# $1 = 'm'
# $2 = 'ming république de Perl'

La première position de chaîne à laquelle cette expression rationnelle peut correspondre est au premier « m » dans « programmation ».
À cette position, le "m{1,2} ?" minimal correspond à un seul « m ». Bien que le deuxième
quantificateur ".*?" préférerait ne correspondre à aucun caractère, il est contraint par la fin de
chaîne d'ancrage "$" pour correspondre au reste de la chaîne.

$x =~ /(.*?)(m{1,2}?)(.*)$/; # allumettes,
# $1 = 'Le programme'
# $2 = 'm'
# $3 = 'ming république de Perl'

Dans cette expression rationnelle, vous pouvez vous attendre au premier quantificateur minimal ".*?" pour correspondre au vide
chaîne, car elle n'est pas contrainte par une ancre "^" pour correspondre au début du mot.
Cependant, le principe 0 s'applique ici. Parce qu'il est possible que l'ensemble de l'expression régulière corresponde
au début de la chaîne, il sera correspond au début de la chaîne. Ainsi le premier
le quantificateur doit tout faire correspondre jusqu'au premier "m". Le deuxième quantificateur minimal
correspond à un seul "m" et le troisième quantificateur correspond au reste de la chaîne.

$x =~ /(.??)(m{1,2})(.*)$/; # allumettes,
# $1 = 'a'
# $2 = 'mm'
# $3 = 're république de Perl'

Tout comme dans l'expression rationnelle précédente, le premier quantificateur ".???" peut correspondre le plus tôt à la position
'a', donc c'est le cas. Le deuxième quantificateur est gourmand, il correspond donc à "mm", et le troisième
correspond au reste de la chaîne.

On peut modifier le principe 3 ci-dessus pour prendre en compte les quantificateurs non gourmands :

· Principe 3 : S'il y a deux éléments ou plus dans une expression rationnelle, le plus à gauche
le quantificateur, le cas échéant, correspondra à autant (peu) de la chaîne que possible
tout en permettant à l'ensemble de l'expression rationnelle de correspondre. Le suivant le plus à gauche gourmand (non gourmand)
le quantificateur, le cas échéant, essaiera de faire correspondre autant (peu) de la chaîne restante
disponible autant que possible, tout en permettant à l'ensemble de l'expression rationnelle de correspondre. Et donc
on, jusqu'à ce que tous les éléments regexp soient satisfaits.

Tout comme l'alternance, les quantificateurs sont également susceptibles de revenir en arrière. Voici une étape-
analyse pas à pas de l'exemple

$x = "le chat au chapeau";
$x =~ /^(.*)(at)(.*)$/; # allumettes,
# $1 = 'le chat dans le h'
# $2 = 'à'
# $3 = '' (0 correspondance)

0 Commencez par la première lettre de la chaîne 't'.

1 Le premier quantificateur '.*' commence par faire correspondre la chaîne entière 'le chat dans le
chapeau'.

2 'a' dans l'élément regexp 'at' ne correspond pas à la fin de la chaîne. Revenir en arrière
caractère.

3 'a' dans l'élément regexp 'at' ne correspond toujours pas à la dernière lettre de la chaîne 't',
alors revenez en arrière sur un personnage de plus.

4 Maintenant, nous pouvons faire correspondre le 'a' et le 't'.

5 Passez au troisième élément '.*'. Puisque nous sommes à la fin de la chaîne et que '.*' peut
correspond à 0 fois, attribuez-lui la chaîne vide.

6 Nous avons terminé !

La plupart du temps, tous ces allers et retours en arrière se produisent rapidement et la recherche
est rapide. Il existe cependant des expressions rationnelles pathologiques dont le temps d'exécution est exponentiellement
grandit avec la taille de la corde. Une structure typique qui vous explose au visage est de
la forme

/(a|b+)*/ ;

Le problème, ce sont les quantificateurs indéterminés imbriqués. Il existe de nombreuses manières différentes de
partitionner une chaîne de longueur n entre le "+" et le "*": une répétition avec "b+" de
longueur n, deux répétitions avec le premier "b+" longueur k et le second avec longueur nk, m
répétitions dont la somme des bits fait n, etc. En fait il y a un nombre exponentiel
des façons de partitionner une chaîne en fonction de sa longueur. Une expression régulière peut avoir de la chance et
faire correspondre au début du processus, mais s'il n'y a pas de correspondance, Perl essaiera chaque possibilité
avant d'abandonner. Soyez donc prudent avec les "*", "{n,m}" et "+" imbriqués. Le livre
mastering Régulier Expressions par Jeffrey Friedl donne une merveilleuse discussion à ce sujet et
d'autres problèmes d'efficacité.

Possessif quantificateurs
Revenir en arrière pendant la recherche incessante d'une correspondance peut être une perte de temps, en particulier
quand le match est voué à l'échec. Considérez le modèle simple

/^\w+\s+\w+$/; # un mot, des espaces, un mot

Chaque fois que cela est appliqué à une chaîne qui ne répond pas tout à fait aux attentes du modèle
tels que "abc" ou "abc def", le moteur regex fera marche arrière, environ une fois pour
chaque caractère de la chaîne. Mais nous savons qu'il n'y a aucun moyen de prendre tous des
caractères du mot initiaux pour correspondre à la première répétition, qui tous les espaces doivent être mangés par
la partie médiane, et il en va de même pour le deuxième mot.

Avec l'introduction du possessif quantificateurs en Perl 5.10, nous avons un moyen de
demandant au moteur de regex de ne pas revenir en arrière, avec les quantificateurs habituels avec un "+"
leur est annexé. Cela les rend aussi gourmands que radins ; une fois qu'ils réussiront, ils ne le feront pas
redonner quoi que ce soit pour permettre une autre solution. Ils ont les significations suivantes :

· "a{n,m}+" signifie : faire correspondre au moins "n" fois, pas plus de "m" fois, autant de fois que
possible, et n'abandonnez rien. "a?+" est l'abréviation de "a{0,1}+"

· "a{n,}+" signifie : faire correspondre au moins "n" fois, mais autant de fois que possible, et ne pas
abandonner n'importe quoi. "a*+" est l'abréviation de "a{0,}+" et "a++" est l'abréviation de "a{1,}+".

· "a{n}+" signifie : correspond exactement à "n" fois. C'est juste là pour la cohérence de la notation.

Ces quantificateurs possessifs représentent un cas particulier d'un concept plus général, le
indépendant sous-expression, voir ci-dessous.

A titre d'exemple où un quantificateur possessif est approprié, nous considérons faire correspondre un entre guillemets
chaîne, telle qu'elle apparaît dans plusieurs langages de programmation. La barre oblique inverse est utilisée comme
caractère d'échappement qui indique que le caractère suivant doit être pris littéralement, comme
un autre caractère pour la chaîne. Par conséquent, après la citation d'ouverture, nous nous attendons à un
(éventuellement vide) séquence d'alternatives : soit un caractère à l'exception d'un guillemet sans échappement
ou une barre oblique inverse ou un caractère d'échappement.

/"(?:[^"\\]++|\\.)*+"/;

Développement a regexp
À ce stade, nous avons couvert tous les concepts de base des expressions régulières, alors donnons une plus
exemple impliqué d'une expression régulière. Nous allons construire une expression rationnelle qui correspond aux nombres.

La première tâche dans la construction d'une expression rationnelle est de décider ce que nous voulons faire correspondre et ce que nous voulons
exclure. Dans notre cas, nous voulons faire correspondre à la fois des nombres entiers et des nombres à virgule flottante et nous
voulez rejeter toute chaîne qui n'est pas un nombre.

La tâche suivante consiste à décomposer le problème en problèmes plus petits qui sont facilement convertis
dans une expression rationnelle.

Le cas le plus simple est celui des nombres entiers. Ceux-ci consistent en une séquence de chiffres, avec une option
signe devant. Les chiffres que nous pouvons représenter avec "\d+" et le signe peuvent être mis en correspondance avec
"[+-]". Ainsi, l'expression rationnelle entière est

/[+-]?\d+/; # correspond à des entiers

Un nombre à virgule flottante a potentiellement un signe, une partie entière, une virgule décimale, un
partie fractionnaire et un exposant. Une ou plusieurs de ces parties sont facultatives, nous devons donc
découvrez les différentes possibilités. Les nombres à virgule flottante qui sont en bonne forme
comprennent 123., 0.345, 34, -1e6 et 25.4E-72. Comme pour les nombres entiers, le front de déconnexion est
complètement facultatif et peut correspondre à "[+-]?". Nous pouvons voir que s'il n'y a pas
exposant, les nombres à virgule flottante doivent avoir une virgule décimale, sinon ce sont des entiers.
Nous pourrions être tentés de les modéliser avec "\d*\.\d*", mais cela correspondrait également à un
point décimal unique, qui n'est pas un nombre. Donc les trois cas de nombre à virgule flottante
sans exposant sont

/[+-]?\d+\./; # 1., 321., etc.
/[+-]?\.\d+/; # .1, .234, etc.
/[+-]?\d+\.\d+/; # 1.0, 30.56, etc.

Ceux-ci peuvent être combinés en une seule expression régulière avec une alternance à trois voies :

/[+-]?(\d+\.\d+|\d+\.|\.\d+)/; # virgule flottante, pas d'exposant

Dans cette alternance, il est important de mettre '\d+\.\d+' avant '\d+\.'. Si '\d+\.' étaient
tout d'abord, l'expression rationnelle correspondrait volontiers à cela et ignorerait la partie fractionnaire du nombre.

Considérons maintenant les nombres à virgule flottante avec exposants. L'observation clé ici est que tous les deux
les entiers et les nombres avec des points décimaux sont autorisés devant un exposant. Puis
les exposants, comme le signe global, sont indépendants de savoir si nous faisons correspondre des nombres avec
ou sans point décimal, et peut être « découplé » de la mantisse. La forme globale de
l'expression régulière devient maintenant claire :

/^(signe facultatif)(entier | fp mantisse)(exposant facultatif)$/;

L'exposant est un "e" ou "E", suivi d'un entier. Donc l'expression rationnelle de l'exposant est

/[eE][+-]?\d+/; # exposant

En rassemblant toutes les parties, nous obtenons une expression rationnelle qui correspond aux nombres :

/^[+-]?(\d+\.\d+|\d+\.|\.\d+|\d+)([eE][+-]?\d+)?$/; # Ta da !

De longues expressions régulières comme celle-ci peuvent impressionner vos amis, mais peuvent être difficiles à déchiffrer. En complexe
des situations comme celle-ci, le modificateur "//x" pour une correspondance est inestimable. Il permet de mettre
des espaces et des commentaires presque arbitraires dans une expression rationnelle sans affecter leur signification.
En l'utilisant, nous pouvons réécrire notre expression rationnelle "étendue" sous la forme la plus agréable

/^
[+-] ? # d'abord, faites correspondre un signe facultatif
( # puis faites correspondre les entiers ou les mantisses fp :
\d+\.\d+ # mantisse de la forme ab
|\d+\. # mantisse de la forme a.
|\.\d+ # mantisse de la forme .b
|\d+ # entier de la forme a
)
([eE][+-]?\d+) ? # enfin, correspondre éventuellement à un exposant
$/x ;

Si les espaces ne sont généralement pas pertinents, comment inclure des caractères d'espace dans une extension
expression régulière ? La réponse est de la barre oblique inverse '\ ' ou de la mettre dans une classe de caractères "[ ]". Le même
pour les dièses : utilisez "\#" ou "[#]". Par exemple, Perl permet un espace entre
le signe et la mantisse ou l'entier, et nous pourrions l'ajouter à notre regexp comme suit :

/^
[+-]?\ * # d'abord, faites correspondre un signe facultatif *et un espace*
( # puis faites correspondre les entiers ou les mantisses fp :
\d+\.\d+ # mantisse de la forme ab
|\d+\. # mantisse de la forme a.
|\.\d+ # mantisse de la forme .b
|\d+ # entier de la forme a
)
([eE][+-]?\d+) ? # enfin, correspondre éventuellement à un exposant
$/x ;

Dans cette forme, il est plus facile d'entrevoir un moyen de simplifier l'alternance. Variantes 1, 2,
et 4 commencent tous par "\d+", donc il pourrait être factorisé :

/^
[+-]?\ * # d'abord, faites correspondre un signe facultatif
( # puis faites correspondre les entiers ou les mantisses fp :
\d+ # commencez par un ...
(
\.\d* # mantisse de la forme ab ou a.
) ? # ? prend en charge les entiers de la forme a
|\.\d+ # mantisse de la forme .b
)
([eE][+-]?\d+) ? # enfin, correspondre éventuellement à un exposant
$/x ;

ou écrit sous la forme compacte,

/^[+-]?\ *(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;

C'est notre dernière expression rationnelle. Pour récapituler, nous avons construit une regexp en

· préciser la tâche en détail,

· décomposer le problème en plus petites parties,

· traduire les petites parties en expressions régulières,

· combiner les expressions régulières,

· et en optimisant l'expression rationnelle combinée finale.

Ce sont également les étapes typiques impliquées dans l'écriture d'un programme informatique. Cela fait
sens parfait, car les expressions régulières sont essentiellement des programmes écrits dans un petit
langage informatique qui spécifie des modèles.

En utilisant Standard expressions in Perl
Le dernier sujet de la partie 1 couvre brièvement comment les expressions rationnelles sont utilisées dans les programmes Perl. Où faire
s'intègrent-ils dans la syntaxe Perl ?

Nous avons déjà introduit l'opérateur de correspondance dans sa valeur par défaut "/regexp/" et arbitraire
délimiteur "m!regexp!" formes. Nous avons utilisé l'opérateur de liaison "=~" et sa négation "!~"
pour tester les correspondances de chaîne. Associé à l'opérateur d'appariement, nous avons discuté de la
modificateurs "//s" sur une seule ligne, " // m ", insensibles à la casse " // i " et étendus " // x ".
Il y a quelques autres choses que vous pourriez vouloir savoir sur les opérateurs de correspondance.

Interdire substitution

Si vous modifiez $pattern après la première substitution, Perl l'ignorera. Si tu
ne voulez aucune substitution du tout, utilisez le délimiteur spécial "m''":

@motif = ('Seuss');
tandis que (<>) {
imprimer si m'@motif'; # correspond au littéral '@pattern', pas à 'Seuss'
}

Semblable aux chaînes, "m''" agit comme des apostrophes sur une expression rationnelle ; tous les autres délimiteurs "m" agissent
comme des citations. Si l'expression rationnelle est évaluée à la chaîne vide, l'expression rationnelle dans le dernier
réussi rencontre est utilisé à la place. Nous avons donc

"chien" =~ /d/; # "d" correspond
"dogbert =~ //; # cela correspond à l'expression rationnelle 'd' utilisée auparavant

Global assorti

Les deux derniers modificateurs dont nous discuterons ici, "//g" et "//c", concernent plusieurs correspondances.
Le modificateur "//g" signifie correspondance globale et permet à l'opérateur de correspondance de correspondre
dans une chaîne autant de fois que possible. Dans un contexte scalaire, les invocations successives
contre une chaîne aura "//g" sauter de match en match, gardant une trace de la position dans
la ficelle au fur et à mesure. Vous pouvez obtenir ou définir la position avec la fonction "pos()".

L'utilisation de "//g" est illustrée dans l'exemple suivant. Supposons que nous ayons une chaîne qui
se compose de mots séparés par des espaces. Si nous savons combien de mots il y a à l'avance, nous
pourrait extraire les mots en utilisant des groupements :

$x = "chat chien maison" ; # 3 mots
$x =~ /^\s*(\w+)\s+(\w+)\s+(\w+)\s*$/; # allumettes,
# $1 = 'chat'
# $2 = 'chien'
# $3 = 'maison'

Mais si nous avions un nombre indéterminé de mots ? C'est le genre de tâche "//g" était
Fait pour Faite pour sert pour sert à. Pour extraire tous les mots, formez l'expression rationnelle simple "(\w+)" et bouclez sur toutes les correspondances
avec "/(\w+)/g":

tandis que ($x =~ /(\w+)/g) {
print "Le mot vaut $1, se termine à la position ", pos $x, "\n" ;
}

impressions

Le mot est chat, se termine à la position 3
Le mot est chien, se termine à la position 7
Le mot est maison, se termine à la position 13

Un échec de correspondance ou une modification de la chaîne cible réinitialise la position. Si vous ne voulez pas le
la position est réinitialisée après un échec de correspondance, ajoutez le "//c", comme dans "/regexp/gc". Le courant
La position dans la chaîne est associée à la chaîne, pas à l'expression rationnelle. Cela signifie que
différentes chaînes ont des positions différentes et leurs positions respectives peuvent être définies ou
lire indépendamment.

Dans le contexte de la liste, "//g" renvoie une liste de regroupements correspondants, ou s'il n'y a aucun regroupement,
une liste de correspondances à l'ensemble de l'expression rationnelle. Donc si nous voulions juste les mots, nous pourrions utiliser

@mots = ($x =~ /(\w+)/g); # allumettes,
# $words[0] = 'chat'
# $words[1] = 'chien'
# $words[2] = 'maison'

L'ancre "\G" est étroitement associée au modificateur "//g". L'ancre "\G" correspond à
le point où la correspondance "//g" précédente s'est arrêtée. "\G" nous permet de faire facilement le contexte-
correspondance sensible :

$métrique = 1 ; # utiliser des unités métriques

$x = ; # lu dans la mesure
$x =~ /^([+-]?\d+)\s*/g; # obtenir l'ampleur
$poids = 1 $ ;
if ($metric) { # vérification d'erreur
print "Erreur d'unités !" sauf si $x =~ /\Gkg\./g;
}
else {
print "Erreur d'unités !" sauf si $x =~ /\Glbs\./g;
}
$x =~ /\G\s+(widget|pignon)/g; # continuer le traitement

La combinaison de "//g" et "\G" nous permet de traiter la chaîne un peu à la fois et d'utiliser
logique Perl arbitraire pour décider quoi faire ensuite. Actuellement, l'ancre "\G" n'est pleinement
pris en charge lorsqu'il est utilisé pour ancrer au début du motif.

"\G" est également inestimable dans le traitement des enregistrements de longueur fixe avec des expressions régulières. Supposons que nous ayons
un extrait de l'ADN de la région codante, codé sous forme de lettres de paires de bases "ATCGTTGAAT..." et nous voulons
pour trouver tous les codons stop "TGA". Dans une région codante, les codons sont des séquences de 3 lettres, donc
nous pouvons considérer l'extrait d'ADN comme une séquence d'enregistrements de 3 lettres. L'expression rationnelle naïve

# développé, c'est "ATC GTT GAA TGC AAA TGA CAT GAC"
$dna = "ATCGTTGAATGCAAATGACATGAC" ;
$adn =~ /TGA/;

ne fonctionne pas ; il peut correspondre à un "TGA", mais il n'y a aucune garantie que le match soit aligné
avec des limites de codon, par exemple, la sous-chaîne "GTT GAA" donne une correspondance. Une meilleure solution est

while ($dna =~ /(\w\w\w)*?TGA/g) { # notez le minimum *?
print "A obtenu un codon d'arrêt TGA à la position ", pos $dna, "\n" ;
}

qui imprime

Vous avez un codon d'arrêt TGA à la position 18
Vous avez un codon d'arrêt TGA à la position 23

La position 18 est bonne, mais la position 23 est fausse. Que s'est-il passé?

La réponse est que notre regexp fonctionne bien jusqu'à ce que nous ayons dépassé la dernière vraie correspondance. Puis le
regexp ne parviendra pas à correspondre à un "TGA" synchronisé et commencera à avancer d'un caractère
position à la fois, pas ce que nous voulons. La solution consiste à utiliser "\G" pour ancrer la correspondance à
l'alignement des codons :

tandis que ($dna =~ /\G(\w\w\w)*?TGA/g) {
print "A obtenu un codon d'arrêt TGA à la position ", pos $dna, "\n" ;
}

Cette imprime

Vous avez un codon d'arrêt TGA à la position 18

Quelle est la bonne réponse. Cet exemple montre qu'il est important non seulement de
correspondre à ce qui est désiré, mais de rejeter ce qui n'est pas désiré.

(Il existe d'autres modificateurs d'expression régulière, tels que "//o", mais leur
les utilisations dépassent le cadre de cette introduction. )

Rechercher et remplacer

Les expressions régulières jouent également un grand rôle dans recherche et remplacer opérations en Perl. Chercher
et remplacer s'effectue avec l'opérateur "s///". La forme générale est
"s/regexp/replacement/modifiers", avec tout ce que nous savons sur les regexps et les modificateurs
s'applique également dans ce cas. Le "remplacement" est une chaîne Perl entre guillemets doubles qui
remplace dans la chaîne tout ce qui correspond à "regexp". L'opérateur "=~" est également
utilisé ici pour associer une chaîne à "s///". S'il correspond à $_, le "$_ =~" peut être
chuté. S'il y a correspondance, "s///" renvoie le nombre de remplacements effectués ; autrement
il retourne faux. Voici quelques exemples:

$x = "Il est temps de nourrir le chat !";
$x =~ s/cat/hacker/; # $x contient « Il est temps de nourrir le pirate ! »
if ($x =~ s/^(Time.*hacker)!$/$1 maintenant !/) {
$plus_insistent = 1 ;
}
$y = "'mots entre guillemets'";
$y =~ s/^'(.*)'$/$1/; # supprime les guillemets simples,
# $y contient des "mots entre guillemets"

Dans le dernier exemple, toute la chaîne correspondait, mais seule la partie à l'intérieur du single
citations a été regroupé. Avec l'opérateur "s///", les variables appariées $1, $2, etc. sont
immédiatement disponible pour une utilisation dans l'expression de remplacement, nous utilisons donc $1 pour remplacer le
chaîne entre guillemets avec juste ce qui a été entre guillemets. Avec le modificateur global, "s///g" recherchera
et remplacez toutes les occurrences de l'expression rationnelle dans la chaîne :

$x = "J'ai frappé 4 pour 4" ;
$x =~ s/4/quatre/; # ne fait pas tout :
# $x contient "J'ai battu quatre pour 4"
$x = "J'ai frappé 4 pour 4" ;
$x =~ s/4/quatre/g; # fait tout :
# $x contient "J'ai battu quatre pour quatre"

Si vous préférez 'regex' à 'regexp' dans ce tutoriel, vous pouvez utiliser le programme suivant
pour le remplacer :

% chat > ​​simple_replace
#!/usr/bin/perl
$regexp = décalage ;
$remplacement = décalage ;
tandis que (<>) {
s/$regexp/$replacement/g ;
imprimer;
}
^D

% simple_replace regexp regex perlretut.pod

Dans "simple_replace", nous avons utilisé le modificateur "s///g" pour remplacer toutes les occurrences de l'expression rationnelle
sur chaque ligne. (Même si l'expression régulière apparaît dans une boucle, Perl est assez intelligent
pour le compiler une seule fois.) Comme avec "simple_grep", le "print" et le
"s/$regexp/$replacement/g" utilise implicitement $_.

Si vous ne voulez pas que "s///" modifie votre variable d'origine, vous pouvez utiliser la méthode non destructive
modificateur de substitution, "s///r". Cela modifie le comportement de sorte que "s///r" renvoie la valeur finale
chaîne substituée (au lieu du nombre de substitutions) :

$x = "J'aime les chiens.";
$y = $x =~ s/chiens/chats/r;
print "$x $y\n" ;

Cet exemple affichera "J'aime les chiens. J'aime les chats". Notez que la variable $x d'origine a
pas été affecté. Le résultat global de la substitution est plutôt stocké dans $y. Si la
la substitution n'affecte rien, la chaîne d'origine est renvoyée :

$x = "J'aime les chiens.";
$y = $x =~ s/éléphants/couguars/r;
print "$x $y\n" ; # imprime "J'aime les chiens. J'aime les chiens."

Une autre chose intéressante que le drapeau "s///r" permet est d'enchaîner les substitutions :

$x = "Les chats sont géniaux.";
print $x =~ s/chats/chiens/r =~ s/chiens/grenouilles/r =~
s/Grenouilles/Hérissons/r, "\n" ;
# affiche "Les hérissons sont géniaux."

Un modificateur disponible spécifiquement pour rechercher et remplacer est l'évaluation "s///e"
modificateur. "s///e" traite le texte de remplacement comme du code Perl, plutôt que comme un guillemet double
chaîne de caractères. La valeur que le code renvoie est remplacée par la sous-chaîne correspondante.
"s///e" est utile si vous avez besoin de faire un peu de calcul dans le processus de remplacement de texte.
Cet exemple compte les fréquences de caractères dans une ligne :

$x = "Facturation du chat" ;
$x =~ s/(.)/$chars{$1}++;$1/ex; # final $1 remplace char par lui-même
print "la fréquence de '$_' est de $cars{$_}\n"
foreach (trier {$chars{$b} <=> $chars{$a}} clés %chars);

Cette imprime

la fréquence de ' ' est 2
la fréquence de 't' est 2
la fréquence de 'l' est 2
la fréquence de 'B' est 1
la fréquence de 'c' est 1
la fréquence de 'e' est 1
la fréquence de 'h' est 1
la fréquence de 'i' est 1
la fréquence de 'a' est 1

Comme avec l'opérateur de correspondance "m//", "s///" peut utiliser d'autres délimiteurs, tels que "s!!!" et
"s{}{}", et même "s{}//". Si des guillemets simples sont utilisés "s'''", alors l'expression rationnelle et
remplacement sont traités comme des chaînes entre guillemets simples et il n'y a pas de substitutions de variables.
"s///" dans le contexte de liste renvoie la même chose que dans le contexte scalaire, c'est-à-dire le nombre de
allumettes.

La scission fonction

La fonction "split()" est un autre endroit où une expression rationnelle est utilisée. "split /regexp/, chaîne,
limit" sépare l'opérande "string" en une liste de sous-chaînes et renvoie cette liste.
L'expression régulière doit être conçue pour correspondre à tout ce qui constitue les séparateurs pour le
sous-chaînes. La « limite », si elle est présente, contraint la division en pas plus de « limite »
nombre de chaînes. Par exemple, pour diviser une chaîne en mots, utilisez

$x = "Calvin et Hobbes" ;
@mots = diviser /\s+/, $x; # $word[0] = 'Calvin'
# $mot[1] = 'et'
# $word[2] = 'Hobbes'

Si l'expression rationnelle vide "//" est utilisée, l'expression rationnelle correspond toujours et la chaîne est divisée en
personnages individuels. Si l'expression rationnelle a des regroupements, la liste résultante contient le
les sous-chaînes correspondantes des groupements également. Par exemple,

$x = "/usr/bin/perl";
@dirs = diviser m!/!, $x; # $dirs[0] = ''
# $dirs[1] = 'usr'
# $dirs[2] = 'bin'
# $dirs[3] = 'perl'
@parts = diviser m!(/)!, $x; # $parts[0] = ''
# $pièces[1] = '/'
# $parts[2] = 'usr'
# $pièces[3] = '/'
# $parts[4] = 'bin'
# $pièces[5] = '/'
# $parts[6] = 'perl'

Étant donné que le premier caractère de $x correspond à l'expression rationnelle, "split" a ajouté une initiale vide
élément à la liste.

Si vous avez lu jusqu'ici, félicitations ! Vous disposez maintenant de tous les outils de base nécessaires à l'utilisation
expressions régulières pour résoudre un large éventail de problèmes de traitement de texte. Si c'est votre
première fois à travers le didacticiel, pourquoi ne pas vous arrêter ici et jouer avec les expressions régulières a
tandis que.... La partie 2 concerne les aspects plus ésotériques des expressions régulières et ceux
les concepts ne sont certainement pas nécessaires dès le départ.

Partie 2: Puissance les outils


OK, vous connaissez les bases des expressions régulières et vous voulez en savoir plus. Si correspondance régulière
expressions est analogue à une promenade dans les bois, alors les outils discutés dans la partie 1 sont
analogue aux cartes topographiques et à une boussole, des outils de base que nous utilisons tout le temps. La plupart des outils
dans la partie 2 sont analogues aux lance-fusées et aux téléphones satellites. Ils ne sont pas utilisés trop souvent sur
une randonnée, mais quand nous sommes coincés, ils peuvent être inestimables.

Ce qui suit sont les capacités plus avancées, moins utilisées ou parfois ésotériques de Perl
expressions régulières. Dans la partie 2, nous supposerons que vous êtes à l'aise avec les bases et que vous vous concentrerez sur
les fonctionnalités avancées.

Plus on personnages, cordes, et caractère les classes
Il existe un certain nombre de séquences d'échappement et de classes de caractères que nous n'avons pas encore abordées.

Il existe plusieurs séquences d'échappement qui convertissent des caractères ou des chaînes entre les majuscules et les
minuscules, et ils sont également disponibles dans les modèles. "\l" et "\u" convertissent le suivant
caractère en minuscule ou majuscule, respectivement :

$x = "perl" ;
$string =~ /\u$x/; # correspond à 'Perl' dans $string
$x = "M(rs?|s)\\."; # notez la double barre oblique inverse
$string =~ /\l$x/; # correspond à 'mr.', 'mrs.' et 'ms.',

Un "\L" ou "\U" indique une conversion durable de la casse, jusqu'à ce qu'il soit terminé par "\E" ou levé
par un autre "\U" ou "\L":

$x = "Ce mot est en minuscule :\L SHOUT\E" ;
$x =~ /crier/; # allumettes
$x = "JE TOUJOURS DES CARTES KEYPUNCH POUR MY 360"
$x =~ /\Ukeypunch/; # correspond à la chaîne de la carte perforée

S'il n'y a pas de "\E", la casse est convertie jusqu'à la fin de la chaîne. Les expressions régulières
"\L\u$word" ou "\u\L$word" convertit le premier caractère de $word en majuscule et le reste
des caractères en minuscules.

Les caractères de contrôle peuvent être échappés avec "\c", de sorte qu'un caractère de contrôle-Z serait
correspond à "\cZ". La séquence d'échappement "\Q"..."\E" entre guillemets ou protège la plupart des non-
caractères alphabétiques. Par exemple,

$x = "\QÇa !^*&%~& chat!";
$x =~ /\Q!^*&%~&\E/; # vérifier le langage grossier

Il ne protège pas "$" ou "@", de sorte que les variables peuvent toujours être substituées.

"\Q", "\L", "\l", "\U", "\u" et "\E" font en fait partie de la syntaxe entre guillemets et non
partie de la syntaxe regexp proprement dite. Ils fonctionneront s'ils apparaissent dans une expression régulière
intégré directement dans un programme, mais pas lorsqu'il est contenu dans une chaîne qui est interpolée dans
un motif.

Les expressions rationnelles Perl peuvent gérer plus que le jeu de caractères ASCII standard. Perl prend en charge
Unicode, une norme pour représenter les alphabets de pratiquement tous les
langues écrites et une multitude de symboles. Les chaînes de texte de Perl sont des chaînes Unicode, donc
ils peuvent contenir des caractères avec une valeur (codepoint ou numéro de caractère) supérieure à 255.

Qu'est-ce que cela signifie pour les expressions régulières ? Eh bien, les utilisateurs d'expressions rationnelles n'ont pas besoin d'en savoir plus sur Perl
représentation interne des chaînes. Mais ils doivent savoir 1) comment représenter Unicode
caractères dans une expression rationnelle et 2) qu'une opération de correspondance traitera la chaîne comme
recherché comme une séquence de caractères, pas d'octets. La réponse à 1) est que Unicode
caractères supérieurs à "chr(255)" sont représentés en utilisant la notation "\x{hex}", car
\x hex (sans accolades) ne va pas plus loin que 255. (À partir de Perl 5.14, si
vous êtes un fan d'octal, vous pouvez aussi utiliser "\o{oct}".)

/\x{263a}/; # correspond à un smiley Unicode :)

REMARQUE: Dans Perl 5.6.0, il fallait dire "utiliser utf8" pour utiliser n'importe quel Unicode
caractéristiques. Ce n'est plus le cas : pour la quasi-totalité des traitements Unicode, l'explicite
Le pragma "utf8" n'est pas nécessaire. (Le seul cas où cela compte est si votre script Perl est en
Unicode et encodé en UTF-8, alors un "utiliser utf8" explicite est nécessaire.)

Déterminer la séquence hexadécimale d'un caractère Unicode que vous voulez ou déchiffrer
l'expression régulière Unicode hexadécimale de quelqu'un d'autre est à peu près aussi amusante que la programmation dans la machine
code. Donc, une autre façon de spécifier les caractères Unicode est d'utiliser le nommé caractère échapper
séquence "\N{Nom}". prénom est un nom pour le caractère Unicode, comme spécifié dans le
Norme Unicode. Par exemple, si nous voulions représenter ou faire correspondre le signe astrologique
pour la planète Mercure, on pourrait utiliser

$x = "abc\N{MERCURY}def" ;
$x =~ /\N{MERCURY}/; # allumettes

On peut aussi utiliser des noms "courts":

print "\N{LETTRE MINUSCULE GRECQUE SIGMA} s'appelle sigma.\n" ;
print "\N{greek:Sigma} est un sigma en majuscule.\n" ;

Vous pouvez également restreindre les noms à un certain alphabet en spécifiant le pragma charnames :

utiliser les charnames qw(grec);
print "\N{sigma} est le sigma grec\n" ;

Un index des noms de personnages est disponible en ligne auprès du Consortium Unicode,
<http://www.unicode.org/charts/charindex.html> ; matériel explicatif avec des liens vers d'autres
ressources àhttp://www.unicode.org/standard/where>.

La réponse à l'exigence 2) est qu'une expression régulière utilise (principalement) des caractères Unicode. le
"principalement" est pour des raisons de compatibilité ascendante désordonnée, mais à partir de Perl 5.14, toute regex
compilé dans le cadre d'une "fonctionnalité d'utilisation 'unicode_strings'" (qui est automatiquement transformée
sur dans le cadre d'un "utiliser 5.012" ou supérieur) transformera "la plupart du temps" en "toujours". Si
vous voulez gérer correctement Unicode, vous devez vous assurer que 'unicode_strings' est activé
au. En interne, il est codé en octets en utilisant soit UTF-8, soit un codage natif de 8 bits,
selon l'historique de la chaîne, mais conceptuellement c'est une séquence de caractères,
pas des octets. Voir perlunitut pour un tutoriel à ce sujet.

Voyons maintenant les classes de caractères Unicode, le plus souvent appelées « propriétés des caractères ».
Ceux-ci sont représentés par la séquence d'échappement "\p{name}". Étroitement associé est le
La propriété "\P{name}", qui est la négation de la "\p{name}". Par exemple, pour faire correspondre
caractères minuscules et majuscules,

$x = "BOB" ;
$x =~ /^\p{EstSupérieur}/; # correspondance, classe de caractères majuscules
$x =~ /^\P{EstSupérieur}/; # ne correspond pas, classe de caractères sans majuscule
$x =~ /^\p{IsLower}/; # ne correspond pas, classe de caractères minuscules
$x =~ /^\P{IsLower}/; # correspondance, classe de caractères sans minuscule

(Le "Est" est facultatif.)

Il existe de très nombreuses propriétés de caractères Unicode. Pour la liste complète, voir perluniprops.
La plupart d'entre eux ont des synonymes avec des noms plus courts, également répertoriés ici. Certains synonymes sont un
seul personnage. Pour ceux-ci, vous pouvez laisser tomber les accolades. Par exemple, "\pM" est le même
chose comme "\p{Mark}", ce qui signifie des choses comme les accents.

La propriété Unicode "\p{Script}" est utilisée pour catégoriser chaque caractère Unicode dans le
script de langue dans lequel il est écrit. Par exemple, l'anglais, le français et un tas d'autres
Les langues européennes sont écrites en écriture latine. Mais il y a aussi l'écriture grecque,
l'écriture thaï, l'écriture katakana, etc. Vous pouvez tester si un personnage est dans un
script particulier avec, par exemple "\p{Latin}", "\p{Greek}", ou "\p{Katakana}". Tester
si ce n'est pas dans le script balinais, vous utiliserez "\P{Balinese}".

Ce que nous avons décrit jusqu'ici est la forme unique des classes de caractères "\p{...}".
Il existe également une forme composée que vous pouvez rencontrer. Ceux-ci ressemblent à "\p{name=value}" ou
"\p{name:value}" (le signe égal et les deux points peuvent être utilisés de manière interchangeable). Ce sont plus
général que la forme simple, et en fait la plupart des formes simples sont juste définies par Perl
raccourcis pour les formes composées courantes. Par exemple, les exemples de script dans le précédent
paragraphe pourrait être écrit de manière équivalente comme "\p{Script=Latin}", "\p{Script:Greek}",
"\p{script=katakana}", et "\P{script=balinese}" (la casse n'a pas d'importance entre le "{}"
croisillons). Vous n'aurez peut-être jamais à utiliser les formes composées, mais il est parfois nécessaire, et
leur utilisation peut rendre votre code plus facile à comprendre.

"\X" est l'abréviation d'une classe de caractères qui comprend un Unicode prolongé graphème
grappe. Cela représente un « caractère logique » : ce qui semble être un seul caractère,
mais peut être représenté en interne par plus d'un. À titre d'exemple, en utilisant l'Unicode complet
noms, par exemple, "A + COMBINING RING" est un groupe de graphèmes avec le caractère de base "A" et
combinant le caractère "COMBINING RING", qui se traduit en danois par A avec le cercle au-dessus
cela, comme dans le mot Aangstrom.

Pour les informations complètes et les plus récentes sur Unicode, consultez la dernière norme Unicode ou le
Site Internet du Consortium Unicodehttp://www.unicode.org>

Comme si toutes ces classes ne suffisaient pas, Perl définit également des classes de caractères de style POSIX.
Ceux-ci ont la forme "[:name:]", avec "name" le nom de la classe POSIX. Le POSIX
les classes sont "alpha", "alnum", "ascii", "cntrl", "digit", "graph", "lower", "print",
"punct", "space", "upper" et "xdigit", et deux extensions, "word" (une extension Perl pour
match "\w"), et "blank" (une extension GNU). Le modificateur "//a" les restreint à
correspondant uniquement dans la plage ASCII ; sinon ils peuvent correspondre au même que leur correspondant
Classes Unicode Perl : "[:upper:]" est identique à "\p{IsUpper}", etc.
exceptions et pièges avec cela; voir perlrecharclass pour une discussion complète.) Le
"[:digit:]", "[:word:]" et "[:space:]" correspondent aux familiers "\d", "\w" et "\s"
classes de personnages. Pour nier une classe POSIX, mettez un "^" devant le nom, de sorte que,
par exemple, "[:^digit:]" correspond à "\D" et, sous Unicode, "\P{IsDigit}". L'Unicode et
Les classes de caractères POSIX peuvent être utilisées comme "\d", à l'exception que POSIX
les classes de caractères ne peuvent être utilisées qu'à l'intérieur d'une classe de caractères :

/\s+[abc[:digit:]xyz]\s*/; # correspond à a,b,c,x,y,z ou à un chiffre
/^=élément\s[[:chiffre:]]/; # correspond à '=élément',
# suivi d'un espace et d'un chiffre
/\s+[abc\p{IsDigit}xyz]\s+/; # correspond à a,b,c,x,y,z ou à un chiffre
/^=item\s\p{IsDigit}/; # correspond à '=élément',
# suivi d'un espace et d'un chiffre

Ouf! C'est tout le reste des personnages et des classes de personnages.

Compilation et économie Standard expressions
Dans la partie 1, nous avons mentionné que Perl compile une expression rationnelle en une séquence compacte d'opcodes.
Ainsi, une expression rationnelle compilée est une structure de données qui peut être stockée une fois et réutilisée et
encore. La citation d'expression régulière "qr//" fait exactement cela : "qr/string/" compile la "string" en tant que
regexp et transforme le résultat en une forme pouvant être affectée à une variable :

$reg = qr/foo+bar?/; # reg contient une expression rationnelle compilée

Ensuite, $reg peut être utilisé comme regexp :

$x = "fooooba" ;
$x =~ $reg; # correspond, tout comme /foo+bar?/
$x =~ /$reg/; # même chose, forme alternative

$reg peut également être interpolé dans une plus grande expression rationnelle :

$x =~ /(abc)?$reg/; # correspond toujours

Comme avec l'opérateur de correspondance, la citation d'expression régulière peut utiliser différents délimiteurs, par exemple,
"qr!!", "qr{}" ou "qr~~". Les apostrophes comme délimiteurs ("qr''") inhibent toute interpolation.

Les expressions régulières précompilées sont utiles pour créer des correspondances dynamiques qui n'ont pas besoin d'être
recompilés à chaque fois qu'ils sont rencontrés. En utilisant des expressions rationnelles précompilées, nous écrivons un
programme "grep_step" qui recherche une séquence de motifs, en passant au motif suivant
dès qu'on a été satisfait.

% chat > ​​grep_step
#!/usr/bin/perl
# grep_step - correspondance expressions régulières, l'une après l'autre
# utilisation : multi_grep regexp1 regexp2 ... fichier1 fichier2 ...

$nombre = décalage ;
$regexp[$_] = décalage pour chaque (0..$nombre-1);
@compiled = map qr/$_/, @regexp;
tandis que ($ligne = <>) {
if ($line =~ /$compilé[0]/) {
imprimer $line ;
décalage @compilé ;
dernier sauf si @compilé ;
}
}
^D

% grep_step 3 shift imprimer dernier grep_step
$nombre = décalage ;
imprimer $line ;
dernier sauf si @compilé ;

Stocker des expressions rationnelles précompilées dans un tableau @compiled nous permet simplement de parcourir en boucle le
regexps sans aucune recompilation, gagnant ainsi en flexibilité sans sacrifier la vitesse.

Composition Standard expressions at d'exécution
Le retour en arrière est plus efficace que les tentatives répétées avec différentes expressions régulières. Si
il existe plusieurs expressions régulières et une correspondance avec l'une d'entre elles est acceptable, alors il
est possible de les combiner en un ensemble d'alternatives. Si les expressions individuelles sont
des données d'entrée, cela peut être fait en programmant une opération de jointure. Nous exploiterons cette idée dans
une version améliorée du programme "simple_grep": un programme qui correspond à plusieurs
modèles:

% chat > ​​multi_grep
#!/usr/bin/perl
# multi_grep - correspond à l'un des expressions régulières
# utilisation : multi_grep regexp1 regexp2 ... fichier1 fichier2 ...

$nombre = décalage ;
$regexp[$_] = décalage pour chaque (0..$nombre-1);
$pattern = join '|', @regexp;

tandis que ($ligne = <>) {
print $ligne si $ligne =~ /$motif/;
}
^D

% multi_grep 2 décalage pour multi_grep
$nombre = décalage ;
$regexp[$_] = décalage pour chaque (0..$nombre-1);

Parfois, il est avantageux de construire un modèle à partir du contribution c'est à analyser
et utilisez les valeurs admissibles sur le côté gauche des opérations d'appariement. En tant que
exemple pour cette situation quelque peu paradoxale, supposons que notre entrée contienne un
verbe de commande qui doit correspondre à l'un des verbes de commande disponibles, avec le
torsion supplémentaire que les commandes peuvent être abrégées tant que la chaîne donnée est unique.
Le programme ci-dessous montre l'algorithme de base.

% chat > ​​correspondance
#!/usr/bin/perl
$kwds = 'copier la liste de comparaison imprimer';
while( $cmd = <> ){
$cmd =~ s/^\s+|\s+$//g; # coupe les espaces de début et de fin
if( ( @matches = $kwds =~ /\b$cmd\w*/g ) == 1 ){
print "commande: '@matches'\n" ;
} elsif( @matches == 0 ){
print "aucune commande de ce type : '$cmd'\n" ;
} Else {
print "non unique : '$cmd' (peut être l'un des suivants : @matches)\n" ;
}
}
^D

% correspondance de clé
li
commande : 'liste'
co
non unique : 'co' (pourrait être l'un de : copier comparer)
imprimante
pas de commande de ce type : 'imprimante'

Plutôt que d'essayer de faire correspondre l'entrée aux mots-clés, nous faisons correspondre l'ensemble combiné de
mots-clés contre l'entrée. L'opération de correspondance de modèle "$kwds =~ /\b($cmd\w*)/g" fait
plusieurs choses à la fois. Il s'assure que la commande donnée commence là où un
le mot-clé commence ("\b"). Il tolère les abréviations dues à l'ajout de "\w*". Il nous dit le
nombre de correspondances ("scalar @matches") et tous les mots-clés qui ont été réellement mis en correspondance.
Vous pourriez difficilement demander plus.

Enrobage commentaires et modificateurs in a Standard expression
En commençant par cette section, nous discuterons de l'ensemble de Perl prolongé motifs. Ces
sont des extensions de la syntaxe d'expression régulière traditionnelle qui fournissent de nouvelles
outils pour la correspondance de motifs. Nous avons déjà vu des extensions sous la forme du minimum
les constructions correspondantes "??", "*?", "+?", "{n,m}?", et "{n,}?". La plupart des extensions ci-dessous
avoir la forme "(?char...)", où le "char" est un caractère qui détermine le type de
extension.

La première extension est un commentaire intégré "(?#text)". Cela intègre un commentaire dans le
expression régulière sans affecter sa signification. Le commentaire ne doit pas avoir de fermeture
parenthèses dans le texte. Un exemple est

/(?# Correspond à un entier :)[+-]?\d+/;

Ce style de commentaire a été largement remplacé par le commentaire brut et libre qui
est autorisé avec le modificateur "//x".

La plupart des modificateurs, tels que "//i", "//m", "//s" et "//x" (ou toute combinaison de ceux-ci) peuvent
également être intégré dans une expression rationnelle en utilisant "(?i)", "(?m)", "(?s)" et "(?x)". Par exemple,

/(?i)oui/; # correspond à la casse 'oui' de manière insensible
/Oui je; # même chose
/(?x)( # version libre d'une expression rationnelle entière
[+-] ? # correspond à un signe facultatif
\d+ # correspond à une séquence de chiffres
)
/X;

Les modificateurs intégrés peuvent avoir deux avantages importants par rapport aux modificateurs habituels. Embarqué
les modificateurs permettent à un ensemble personnalisé de modificateurs de chacun modèle d'expression régulière. C'est super pour
correspondant à un tableau d'expressions rationnelles qui doivent avoir des modificateurs différents :

$pattern[0] = '(?i)docteur';
$motif[1] = 'Johnson';

tandis que (<>) {
foreach $patt (@motif) {
imprimer si /$patt/;
}
}

Le deuxième avantage est que les modificateurs embarqués (sauf "//p", qui modifie l'intégralité de
regexp) n'affectent que l'expression rationnelle à l'intérieur du groupe dans lequel le modificateur intégré est contenu.
le regroupement peut être utilisé pour localiser les effets du modificateur :

/Réponse : ((?i)oui)/ ; # correspond à 'Réponse : oui', 'Réponse : OUI', etc.

Les modificateurs intégrés peuvent également désactiver tous les modificateurs déjà présents en utilisant, par exemple,
"(?-je)". Les modificateurs peuvent également être combinés en une seule expression, par exemple, "(?si)" s'active
mode ligne unique et désactive l'insensibilité à la casse.

Des modificateurs intégrés peuvent également être ajoutés à un groupe sans capture. "(?im:regexp)" est un
regroupement sans capture qui correspond à la casse "regexp" de manière insensible et désactive le multiligne
mode.

Vous recherchez devant et recherchez- derrière
Cette section concerne les assertions lookahead et lookbehind. D'abord, un peu
fond.

Dans les expressions régulières Perl, la plupart des éléments d'expression régulière "mangent" une certaine quantité de chaîne lorsque
ils correspondent. Par exemple, l'élément regexp "[abc}]" consomme un caractère de la chaîne
quand il correspond, dans le sens où Perl passe à la position de caractère suivante dans la chaîne
Après le match. Il y a certains éléments, cependant, qui ne mangent pas les personnages (avance
la position du caractère) s'ils correspondent. Les exemples que nous avons vus jusqu'à présent sont les ancres.
L'ancre "^" correspond au début de la ligne, mais ne mange aucun caractère.
De même, l'ancre de limite de mot "\b" correspond à chaque fois qu'un caractère correspondant à "\w" est
à côté d'un personnage qui ne le fait pas, mais il ne mange aucun personnage lui-même. Ancres
sont des exemples de largeur zéro affirmations: de largeur nulle, car ils ne consomment aucun caractère, et
assertions, car elles testent certaines propriétés de la chaîne. Dans le cadre de notre promenade
l'analogie de Woods avec la correspondance d'expressions rationnelles, la plupart des éléments d'expressions rationnelles nous déplacent le long d'une piste, mais
les ancres nous font nous arrêter un instant et vérifier notre environnement. Si l'environnement local vérifie
dehors, nous pouvons avancer. Mais si l'environnement local ne nous satisfait pas, il faut
faire marche arrière.

Vérifier l'environnement consiste soit à regarder devant le sentier, soit derrière, soit
les deux. "^" regarde derrière, pour voir qu'il n'y a pas de caractères avant. "$" regarde en avant, pour
voir qu'il n'y a pas de caractères après. "\b" regarde à la fois devant et derrière, pour voir si le
les caractères de chaque côté diffèrent dans leur "mot-ness".

Les assertions lookahead et lookbehind sont des généralisations du concept d'ancrage.
Lookahead et lookbehind sont des assertions de largeur zéro qui nous permettent de spécifier quels caractères nous
veux tester. L'assertion lookahead est notée "(?=regexp)" et l'assertion lookbehind
l'assertion est notée "(?<=fixed-regexp)". Certains exemples sont

$x = "J'attrape le chat domestique 'Tom-cat' avec de l'herbe à chat";
$x =~ /cat(?=\s)/; # correspond à 'cat' dans 'housecat'
@catwords = ($x =~ /(?<=\s)cat\w+/g); # allumettes,
# $catwords[0] = 'attraper'
# $catwords[1] = 'herbe à chat'
$x =~ /\bcat\b/; # correspond à 'cat' dans 'Tom-cat'
$x =~ /(?<=\s)cat(?=\s)/; # ne correspond pas ; pas de 'chat' isolé dans
# milieu de $x

Notez que les parenthèses dans "(?=regexp)" et "(?<=regexp)" ne sont pas capturantes, car elles
sont des assertions de largeur zéro. Ainsi dans la deuxième regexp, les sous-chaînes capturées sont celles
de l'ensemble de l'expression régulière elle-même. Lookahead "(?=regexp)" peut correspondre à des expressions rationnelles arbitraires, mais
lookbehind "(?<=fixed-regexp)" ne fonctionne que pour les expressions rationnelles de largeur fixe, c'est-à-dire un nombre fixe
de caractères longtemps. Ainsi "(?<=(ab|bc))" est bien, mais "(?<=(ab)*)" ne l'est pas. Le nié
les versions des assertions lookahead et lookbehind sont désignées par "(?!regexp)" et
"(? pas rencontre:

$x = "foobar" ;
$x =~ /foo(?!bar)/; # ne correspond pas, 'bar' suit 'foo'
$x =~ /foo(?!baz)/; # correspond, 'baz' ne suit pas 'foo'
$x =~ /(?

Le "\C" n'est pas pris en charge dans lookbehind, car la définition déjà traîtresse de "\C"
le deviendrait encore plus en reculant.

Voici un exemple où une chaîne contenant des mots séparés par des blancs, des nombres et des
tirets doit être divisé en ses composants. Utiliser "/\s+/" seul ne fonctionnera pas, car les espaces
ne sont pas requis entre les tirets, ou un mot ou un tiret. Des places supplémentaires pour une scission sont
établi en regardant devant et derrière :

$str = "un deux - --6-8" ;
@toks = split / \s+ # une suite d'espaces
| (?<=\S) (?=-) # tout autre espace suivi de '-'
| (?<=-) (?=\S) # un '-' suivi de tout autre espace
/x, $str; # @toks = qw(un deux - - - 6 - 8)

En utilisant indépendant sous-expressions à empêcher retour en arrière
Fournisseur sous-expressions sont des expressions régulières, dans le contexte d'une plus grande régularité
expression, qui fonctionnent indépendamment de l'expression régulière plus grande. c'est-à-dire qu'ils
consomment autant ou aussi peu de corde qu'ils le souhaitent sans tenir compte de la capacité de
l'expression régulière la plus grande pour correspondre. Les sous-expressions indépendantes sont représentées par "(?>regexp)".
Nous pouvons illustrer leur comportement en considérant d'abord une expression rationnelle ordinaire :

$x = "ab" ;
$x =~ /a*ab/; # allumettes

Cela correspond évidemment, mais dans le processus de correspondance, la sous-expression "a*" d'abord
a attrapé le "a". Cependant, cela ne permettrait pas à l'ensemble de l'expression régulière de correspondre, donc après
retour en arrière, "a*" a finalement rendu le "a" et correspond à la chaîne vide. Tiens, quoi
"a*" correspondait était dépendant sur ce à quoi correspond le reste de l'expression rationnelle.

Comparez cela avec une sous-expression indépendante :

$x =~ /(?>a*)ab/; # ne correspond pas !

La sous-expression indépendante "(?>a*)" ne se soucie pas du reste de l'expression rationnelle, donc elle
voit un "a" et l'attrape. Ensuite, le reste de l'expression rationnelle "ab" ne peut pas correspondre. Parce que
"(?>a*)" est indépendant, il n'y a pas de retour en arrière et la sous-expression indépendante le fait
pas abandonner son "a". Ainsi, la correspondance de l'expression rationnelle dans son ensemble échoue. Un comportement similaire
se produit avec des expressions rationnelles complètement indépendantes :

$x = "ab" ;
$x =~ /a*/g; # correspond, mange un 'a'
$x =~ /\Gab/g; # ne correspond pas, pas de 'a' disponible

Ici, "//g" et "\G" créent un transfert "tag team" de la chaîne d'une expression rationnelle à la
autre. Les expressions régulières avec une sous-expression indépendante ressemblent beaucoup à ceci, avec un transfert de
la chaîne à la sous-expression indépendante, et un transfert de la chaîne à la
regexp englobante.

La capacité d'une sous-expression indépendante à empêcher le retour en arrière peut être très utile.
Supposons que nous voulions faire correspondre une chaîne non vide entre parenthèses jusqu'à deux niveaux de profondeur.
Ensuite, l'expression régulière suivante correspond :

$x = "abc(de(fg)h" ; # parenthèses déséquilibrées
$x =~ /\( ( [^()]+ | \([^()]*\) )+ \)/x;

L'expression rationnelle correspond à une parenthèse ouverte, une ou plusieurs copies d'une alternance et une fermeture
parenthèse. L'alternance est bidirectionnelle, la première alternative "[^()]+" correspondant à un
sous-chaîne sans parenthèses et la deuxième alternative "\([^()]*\)" correspondant à un
sous-chaîne délimitée par des parenthèses. Le problème avec cette expression rationnelle est qu'elle est
pathologique : il a imbriqué des quantificateurs indéterminés de la forme "(a+|b)+". Nous avons discuté
dans la partie 1 comment les quantificateurs imbriqués comme celui-ci pourraient prendre un temps exponentiellement long pour
exécuter s'il n'y avait pas de correspondance possible. Pour éviter l'explosion exponentielle, nous devons
empêcher un retour en arrière inutile à un moment donné. Cela peut être fait en enfermant l'intérieur
quantificateur en tant que sous-expression indépendante :

$x =~ /\( ( (?>[^()]+) | \([^()]*\) )+ \)/x;

Ici, "(?>[^()]+)" brise la dégénérescence du partitionnement de chaînes en engloutissant autant de
la ficelle que possible et en la gardant. Ensuite, les échecs de match échouent beaucoup plus rapidement.

Conditionnel expressions
A conditionnels. expression est une forme d'instruction if-then-else qui permet de choisir
quels modèles doivent être mis en correspondance, en fonction de certaines conditions. Il existe deux types de
expression conditionnelle : "(?(condition)yes-regexp)" et
"(?(condition)oui-expression rationnelle|non-expression rationnelle)". "(?(condition)yes-regexp)" est comme un 'if () {}'
déclaration en Perl. Si la "condition" est vraie, le "yes-regexp" sera mis en correspondance. Si la
"condition" est faux, le "yes-regexp" sera ignoré et Perl passera au suivant
élément d'expression régulière. La seconde forme ressemble à une instruction 'if () {} else {}' en Perl. Si la
"condition" est vrai, le "yes-regexp" sera mis en correspondance, sinon le "no-regexp" sera
assorti.

La "condition" peut prendre plusieurs formes. La première forme est simplement un entier dans
parenthèses "(entier)". C'est vrai si la référence arrière correspondante "\integer" correspond
plus tôt dans l'expression régulière. La même chose peut être faite avec un nom associé à une capture
groupe, écrit comme "( )" ou "('name')". La deuxième forme est une largeur nulle nue
assertion "(?...)", soit un lookahead, un lookbehind, ou une assertion de code (discutée dans
la section suivante). Le troisième ensemble de formulaires fournit des tests qui renvoient vrai si le
l'expression est exécutée dans une récursivité ("(R)") ou est appelée à partir d'une capture
groupe, référencé soit par un numéro ("(R1)", "(R2)",...) soit par un nom ("(R&nom)").

La forme entière ou nominative de la "condition" permet de choisir, avec plus de souplesse,
quoi faire correspondre en fonction de ce qui correspondait plus tôt dans l'expression régulière. Ceci recherche les mots du
forme "$x$x" ou "$x$y$y$x" :

% simple_grep '^(\w+)(\w+)?(?(2)\g2\g1|\g1)$' /usr/dict/words
béribéri
noix de coco
couscous
acte

siffler
toto
tutu

La "condition" lookbehind permet, avec les références arrière, une partie plus tôt du match
pour influencer une partie ultérieure du match. Par exemple,

/[ATGC]+(?(?<=AA)G|C)$/;

correspond à une séquence d'ADN telle qu'elle se termine soit par "AAG", soit par une autre paire de bases
combinaison et "C". Notez que la forme est "(?(?<=AA)G|C)" et non "(?((?<=AA))G|C)" ; pour
les assertions lookahead, lookbehind ou code, les parenthèses autour du conditionnel sont
pas besoin.

Définir nommé motifs
Certaines expressions régulières utilisent des sous-modèles identiques à plusieurs endroits. Commencer avec Perl
5.10, il est possible de définir des sous-modèles nommés dans une section du modèle afin qu'ils
peut être appelé par son nom n'importe où dans le motif. Ce modèle syntaxique pour ce
le groupe de définition est "(?(DEFINE)(? motif)...)". L'insertion d'un motif nommé est
écrit comme "(?&nom)".

L'exemple ci-dessous illustre cette fonctionnalité en utilisant le modèle pour les nombres à virgule flottante
qui a été présenté plus tôt. Les trois sous-modèles qui sont utilisés plus d'une fois sont les
signe facultatif, la séquence de chiffres pour un nombre entier et la fraction décimale. Le DÉFINIR
groupe à la fin du motif contient leur définition. Notez que la décimale
le modèle de fraction est le premier endroit où nous pouvons réutiliser le modèle d'entier.

/^ (?&osg)\ * ( (?&int)(?&dec)? | (?&dec) )
(? : [eE](?&osg)(?&int) ) ?
$
(?(DÉFINIR)
(? [-+]?) # signe facultatif
(? \d++) # entier
(? \.(?&int)) # fraction décimale
)/X

Récursif motifs
Cette fonctionnalité (introduite dans Perl 5.10) étend considérablement la puissance du modèle de Perl
correspondant à. En se référant à un autre groupe de capture n'importe où dans le modèle avec le
construire "(?group-ref)", le modèle au sein du groupe référencé est utilisé comme un
sous-modèle indépendant à la place de la référence de groupe elle-même. Parce que le groupe
la référence peut être contenue dans les le groupe auquel il se réfère, il est désormais possible de postuler
correspondance de modèle à des tâches qui nécessitaient jusqu'à présent un analyseur récursif.

Pour illustrer cette fonctionnalité, nous allons concevoir un modèle qui correspond si une chaîne contient un
palindrome. (Il s'agit d'un mot ou d'une phrase qui, tout en ignorant les espaces, l'interponctuation
et la casse, se lit de la même manière à l'envers qu'à l'avant. Commençons par observer que le vide
chaîne ou une chaîne contenant un seul caractère de mot est un palindrome. Sinon il faut
avoir un caractère de mot à l'avant et le même à sa fin, avec un autre palindrome dans
entre.

/(?: (\w) (?...Voici un palindrome...) \g{-1} | \w? )/x

En ajoutant "\W*" à chaque extrémité pour éliminer ce qui doit être ignoré, nous avons déjà le plein
modèle:

mon $pp = qr/^(\W* (?: (\w) (?1) \g{-1} | \w? ) \W*)$/ix;
pour $s ( "saippuakauppias", "Un homme, un plan, un canal : Panama !" ){
print "'$s' est un palindrome\n" if $s =~ /$pp/;
}

Dans "(?...)" des références arrières absolues et relatives peuvent être utilisées. L'ensemble du motif peut
être réinséré avec "(?R)" ou "(?0)". Si vous préférez nommer vos groupes, vous pouvez utiliser
"(?&nom)" pour revenir dans ce groupe.

A Bits of la magie: exécution Perl code in a Standard expression
Normalement, les expressions rationnelles font partie des expressions Perl. Code évaluation les expressions tournent ça
en autorisant du code Perl arbitraire à faire partie d'une expression rationnelle. Une évaluation de code
l'expression est notée "(?{code})", avec code une chaîne d'instructions Perl.

Soyez averti que cette fonctionnalité est considérée comme expérimentale et peut être modifiée sans préavis.

Les expressions de code sont des assertions de largeur nulle et la valeur qu'elles renvoient dépend de leur
environnement. Il y a deux possibilités : soit l'expression de code est utilisée comme un
conditionnel dans une expression conditionnelle "(?(condition)...)", ou ce n'est pas le cas. Si le code
expression est une conditionnelle, le code est évalué et le résultat (c'est-à-dire le résultat de la
dernière déclaration) est utilisé pour déterminer la vérité ou le mensonge. Si l'expression de code n'est pas
utilisé comme conditionnel, l'assertion évalue toujours vrai et le résultat est mis dans le
variable spéciale $^R. La variable $^R peut ensuite être utilisée dans des expressions de code plus tard dans le
expression rationnelle. Voici quelques exemples idiots :

$x = "abcdef" ;
$x =~ /abc(?{print "Salut maman!";})def/; # allumettes,
# affiche 'Salut maman !'
$x =~ /aaa(?{print "Salut maman!";})def/; # ne correspond pas,
# non 'Salut maman !'

Prêtez une attention particulière à l'exemple suivant :

$x =~ /abc(?{print "Salut maman!";})ddd/; # ne correspond pas,
# non 'Salut maman !'
# mais pourquoi pas?

À première vue, on pourrait penser qu'il ne devrait pas s'imprimer, car évidemment le "ddd" n'est pas
va correspondre à la chaîne cible. Mais regardez cet exemple :

$x =~ /abc(?{print "Salut maman!";})[dD]dd/; # ne correspond pas,
# mais _imprime_

Hmm. Que s'est-il passé ici? Si vous avez suivi, vous savez que le modèle ci-dessus
devrait être effectivement (presque) le même que le dernier ; enfermant le "d" dans un caractère
la classe ne va pas changer ce qu'elle correspond. Alors pourquoi le premier n'imprime-t-il pas alors que le
le deuxième le fait ?

La réponse réside dans les optimisations apportées par le moteur de regex. Dans le premier cas, tous les
le moteur voit ce sont de simples caractères anciens (à part la construction "?{}"). C'est assez intelligent
pour se rendre compte que la chaîne 'ddd' ne se produit pas dans notre chaîne cible avant réellement
exécuter le motif à travers. Mais dans le second cas, nous l'avons fait croire que
notre modèle est plus compliqué. Il jette un œil, voit notre classe de personnage et décide
qu'il devra réellement exécuter le modèle pour déterminer s'il correspond ou non, et
en cours d'exécution, il atteint l'instruction print avant de découvrir que nous ne
avoir un match.

Pour voir de plus près comment le moteur effectue les optimisations, voir la section "Pragmas et
débogage" ci-dessous.

Plus de fun avec "?{}":

$x =~ /(?{print "Salut maman!";})/; # allumettes,
# affiche 'Salut maman !'
$x =~ /(?{$c = 1;})(?{print "$c";})/; # allumettes,
# affiche '1'
$x =~ /(?{$c = 1;})(?{print "$^R";})/; # allumettes,
# affiche '1'

Le peu de magie mentionné dans le titre de la section se produit lorsque l'expression rationnelle revient en arrière dans le
processus de recherche d'une correspondance. Si l'expression rationnelle revient sur une expression de code et si
les variables utilisées à l'intérieur sont localisées en utilisant "local", les changements dans les variables
produits par l'expression de code sont annulés ! Ainsi, si nous voulions compter combien de fois un
caractère a été apparié à l'intérieur d'un groupe, nous pourrions utiliser, par exemple,

$x = "aaaa" ;
$compte = 0 ; # initialiser 'un' compte
$c = "bob" ; # teste si $c est écrasé
$x =~ /(?{local $c = 0;}) # initialiser le nombre
( un # correspond à 'a'
(?{local $c = $c + 1;}) # nombre d'incréments
)* # faites-le autant de fois que vous le souhaitez,
aa # mais correspond à 'aa' à la fin
(?{$count = $c;}) # copie la var locale $c dans $count
/X;
print "'a' count est $count, \$c variable est '$c'\n" ;

Cette imprime

'a' compte est 2, la variable $c est 'bob'

Si on remplace le " (?{local $c = $c + 1;})" par " (?{$c = $c + 1;})", la variable
les changements sont pas annulé pendant le retour en arrière, et nous obtenons

'a' compte est 4, la variable $c est 'bob'

Notez que seuls les changements de variables localisés sont annulés. Autres effets secondaires du code
l'exécution de l'expression sont permanentes. Ainsi

$x = "aaaa" ;
$x =~ /(a(?{print "Yow\n";}))*aa/;

produit

Yow
Yow
Yow
Yow

Le résultat $^R est automatiquement localisé, afin qu'il se comporte correctement en présence
de faire marche arrière.

Cet exemple utilise une expression de code dans un conditionnel pour correspondre à un article défini, soit
'the' en anglais ou 'der|die|das' en allemand :

$lang = 'DE'; # utiliser l'allemand

$text = "das" ;
imprimer "correspondant\n"
si $texte =~ /(?(?{
$lang eq 'EN'; # la langue est-elle l'anglais ?
})
le | # si c'est le cas, alors faites correspondre 'le'
(der|die|das) # autre, correspond à 'der|die|das'
)
/xi;

Notez que la syntaxe ici est "(?(?{...})yes-regexp|no-regexp)", pas
"(?((?{...}))yes-regexp|no-regexp)". En d'autres termes, dans le cas d'une expression de code, nous
pas besoin de parenthèses supplémentaires autour du conditionnel.

Si vous essayez d'utiliser des expressions de code où le texte du code est contenu dans un
variable, plutôt que d'apparaître littéralement dans le motif, Perl peut vous surprendre :

$bar = 5 ;
$pat = '(?{ 1 })';
/foo(?{ $bar })bar/; # compile ok, $bar non interpolé
/foo(?{ 1 })$bar/; # compile ok, $bar interpolé
/foo${pat}bar/; # erreur de compilation !

$pat = qr/(?{ $foo = 1 })/; # regexp de code de précompilation
/foo${pat}bar/; # compile bien

Si une expression régulière a une variable qui interpole une expression de code, Perl traite l'expression régulière comme
une erreur. Si l'expression de code est précompilée dans une variable, cependant, l'interpolation est
d'accord. La question est, pourquoi est-ce une erreur?

La raison en est que l'interpolation des variables et les expressions de code constituent ensemble une sécurité
risque. La combinaison est dangereuse car de nombreux programmeurs qui écrivent des moteurs de recherche
prennent souvent l'entrée de l'utilisateur et la branchent directement dans une expression rationnelle :

$regexp = <> ; # lecture de l'expression régulière fournie par l'utilisateur
$chomp $regexp; # se débarrasser d'une éventuelle nouvelle ligne
$texte =~ /$regexp/; # recherche $text pour $regexp

Si la variable $regexp contient une expression de code, l'utilisateur peut alors exécuter arbitrairement
Code Perl. Par exemple, un joker pourrait rechercher "system('rm -rf *');" pour effacer votre
des dossiers. En ce sens, la combinaison d'interpolations et d'expressions de code des souillures votre
expression rationnelle. Donc, par défaut, en utilisant à la fois l'interpolation et les expressions de code dans la même expression rationnelle
n'est pas autorisé. Si vous n'êtes pas préoccupé par les utilisateurs malveillants, il est possible de contourner
ce contrôle de sécurité en appelant "use re 'eval'":

utiliser re « eval » ; # jette la prudence par la porte
$bar = 5 ;
$pat = '(?{ 1 })';
/foo${pat}bar/; # compile bien

Une autre forme d'expression de code est le modèle code expression. Le code de modèle
expression est comme une expression de code régulière, sauf que le résultat du code
évaluation est traitée comme une expression régulière et mise en correspondance immédiatement. Un exemple simple
is

$longueur = 5 ;
$char = 'a';
$x = 'aaaaabb';
$x =~ /(??{$char x $length})/x; # correspondance, il y en a 5 sur 'a'

Ce dernier exemple contient à la fois des expressions de code ordinaire et de modèle. Il détecte
si une chaîne binaire 1101010010001... a un espacement de Fibonacci 0,1,1,2,3,5,... de la
1 :

$x = "1101010010001000001" ;
$z0 = ''; $z1 = '0'; # conditions initiales
print "C'est une suite de Fibonacci\n"
if $x =~ /^1 # correspond à un '1' initial
(?:
((??{ $z0 })) # correspond à un '0'
1 # puis un '1'
(?{ $z0 = $z1; $z1 .= $^N; })
)+ # répéter au besoin
$ # c'est tout ce qu'il y a
/X;
printf "La plus grande séquence trouvée était %d\n", length($z1)-length($z0) ;

N'oubliez pas que $^N est défini sur ce qui correspond au dernier groupe de capture terminé. Cette
impressions

C'est une suite de Fibonacci
La plus grande séquence appariée était 5

Ha! Essayez cela avec votre package d'expression régulière de variété de jardin...

Notez que les variables $z0 et $z1 ne sont pas substituées lorsque l'expression rationnelle est compilée, car
se produit pour les variables ordinaires en dehors d'une expression de code. Au contraire, l'ensemble du bloc de code est
analysé en tant que code perl en même temps que perl compile le code contenant le littéral
modèle d'expression régulière.

L'expression rationnelle sans le modificateur "//x" est

/^1(?:((??{ $z0 }))1(?{ $z0 = $z1; $z1 .= $^N; }))+$/

ce qui montre que des espaces sont encore possibles dans les parties de code. Néanmoins, lorsque vous travaillez
avec le code et les expressions conditionnelles, la forme étendue des expressions rationnelles est presque nécessaire dans
créer et déboguer des expressions régulières.

Revenant des bactéries verbes
Perl 5.10 a introduit un certain nombre de verbes de contrôle destinés à fournir un contrôle détaillé sur
le processus de retour en arrière, en influençant directement le moteur de regexp et en fournissant
techniques de surveillance. Comme toutes les fonctionnalités de ce groupe sont expérimentales et sujettes à
modification ou suppression dans une future version de Perl, le lecteur intéressé est
"Verbes de contrôle de backtracking spéciaux" en perlre pour une description détaillée.

Ci-dessous est juste un exemple, illustrant le verbe de contrôle "(*FAIL)", qui peut être
abrégé en "(*F)". Si cela est inséré dans une expression rationnelle, cela entraînera son échec, tout comme
il y aurait une certaine incompatibilité entre le motif et la chaîne. Traitement de l'expression régulière
continue comme après toute panne "normale", de sorte que, par exemple, la position suivante
dans la chaîne ou une autre alternative sera essayée. Comme ne pas correspondre ne préserve pas
capturer des groupes ou produire des résultats, il peut être nécessaire de l'utiliser en combinaison avec
code embarqué.

%compte = ();
"supercalifragilisticexpialidocious" =~
/([aeiou])(?{ $count{$1}++ ; })(*FAIL)/i ;
printf "%3d '%s'\n", $count{$_}, $_ for (clés de tri %count);

Le modèle commence par une classe correspondant à un sous-ensemble de lettres. Chaque fois que cela correspond, un
déclaration comme "$count{'a'}++;" est exécuté, en incrémentant le compteur de lettres. Puis
"(*FAIL)" fait ce qu'il dit, et le moteur d'expression régulière procède conformément au livre : tant que
comme la fin de la chaîne n'est pas atteinte, la position est avancée avant de rechercher
une autre voyelle. Ainsi, match ou no match ne fait aucune différence, et le moteur d'expression régulière continue
jusqu'à ce que la chaîne entière ait été inspectée. (Il est remarquable qu'une solution alternative
en utilisant quelque chose comme

$count{lc($_)}++ pour split('', "supercalifragilisticexpialidocious");
printf "%3d '%s'\n", $count2{$_}, $_ for ( qw{ aeiou } );

est considérablement plus lent.)

Pragmatiques et débogage
En parlant de débogage, il existe plusieurs pragmas disponibles pour contrôler et déboguer les expressions régulières dans
Perl. Nous avons déjà rencontré un pragma dans la section précédente, "use re 'eval';",
qui permet à l'interpolation de variable et aux expressions de code de coexister dans une expression rationnelle. L'autre
les pragmes sont

utiliser re « contamination » ;
$ entaché = <> ;
@parts = ($ souillé =~ /(\w+)\s+(\w+)/; # @parts est maintenant souillé

Le pragma "tainte" fait que toutes les sous-chaînes d'une correspondance avec une variable contaminée sont
entaché aussi. Ce n'est normalement pas le cas, car les expressions rationnelles sont souvent utilisées pour extraire le
bits sûrs d'une variable contaminée. Utilisez "taint" lorsque vous n'extrayez pas de bits sûrs, mais
effectuent un autre traitement. Les pragmas « taint » et « eval » sont tous deux lexicalement
étendue, ce qui signifie qu'ils ne sont en vigueur que jusqu'à la fin du bloc renfermant le
pragmes.

utilisez re '/m'; # ou tout autre indicateur
$chaîne_multiligne =~ /^foo/; # /m est implicite

Le pragma "re '/flags'" (introduit dans Perl 5.14) active l'expression régulière donnée
jusqu'à la fin de la portée lexicale. Voir "mode '/flags'" dans re pour plus de détails.

utilisez re 'debug';
/^(.*)$/s; # informations de débogage de sortie

utilisez re 'debugcolor';
/^(.*)$/s; # sortie des informations de débogage en couleur vivante

Les pragmas globaux "debug" et "debugcolor" permettent d'obtenir des informations de débogage détaillées sur
compilation et exécution d'expressions rationnelles. "debugcolor" est le même que debug, sauf le débogage
les informations sont affichées en couleur sur des terminaux pouvant afficher des séquences de couleurs termcap.
Voici un exemple de sortie :

% perl -e 'use re "debug" ; "abc" =~ /a*b+c/;'
Compilation de REx 'a*b+c'
taille 9 premier à 1
1: STAR(4)
2: EXACT (0)
4: PLUS(7)
5: EXACT (0)
7 : EXACT (9)
9: FIN(0)
flottant 'bc' à 0..2147483647 (vérification flottante) minlen 2
Deviner le début du match, REx 'a*b+c' contre 'abc'...
Substr flottante 'bc' trouvée à l'offset 1...
Deviné : correspond à l'offset 0
Faire correspondre REx 'a*b+c' contre 'abc'
Définition d'une portée EVAL, savestack=3
0 <> | 1 : ÉTOILE
EXACT peut correspondre 1 fois sur 32767...
Définition d'une portée EVAL, savestack=3
1 | 4: PLUS
EXACT peut correspondre 1 fois sur 32767...
Définition d'une portée EVAL, savestack=3
2 | 7 : EXACT
3 <> | 9 : FIN
Match réussi !
Libérer REx : 'a*b+c'

Si vous êtes allé aussi loin dans le didacticiel, vous pouvez probablement deviner quelles sont les différentes
des parties de la sortie de débogage vous le disent. La première partie

Compilation de REx 'a*b+c'
taille 9 premier à 1
1: STAR(4)
2: EXACT (0)
4: PLUS(7)
5: EXACT (0)
7 : EXACT (9)
9: FIN(0)

décrit l'étape de compilation. STAR(4) signifie qu'il y a un objet étoilé, dans ce
cas 'a', et s'il correspond, allez à la ligne 4, c'est-à-dire, PLUS(sept). Les lignes médianes décrivent certains
heuristiques et optimisations effectuées avant un match :

flottant 'bc' à 0..2147483647 (vérification flottante) minlen 2
Deviner le début du match, REx 'a*b+c' contre 'abc'...
Substr flottante 'bc' trouvée à l'offset 1...
Deviné : correspond à l'offset 0

Ensuite, le match est exécuté et les lignes restantes décrivent le processus :

Faire correspondre REx 'a*b+c' contre 'abc'
Définition d'une portée EVAL, savestack=3
0 <> | 1 : ÉTOILE
EXACT peut correspondre 1 fois sur 32767...
Définition d'une portée EVAL, savestack=3
1 | 4: PLUS
EXACT peut correspondre 1 fois sur 32767...
Définition d'une portée EVAL, savestack=3
2 | 7 : EXACT
3 <> | 9 : FIN
Match réussi !
Libérer REx : 'a*b+c'

Chaque étape est de la forme "n ", avec " " la partie de la chaîne correspondante et " "
la pièce n'a pas encore correspondu. Le " | 1 : STAR " indique que Perl est à la ligne numéro 1 dans le
liste de compilation ci-dessus. Voir "Déboguer les expressions régulières" dans perldebguts pour bien plus
détail.

Une autre méthode de débogage des expressions régulières consiste à incorporer des instructions "print" dans le
expression rationnelle. Cela fournit un compte rendu détaillé du retour en arrière dans une alternance :

"that this" =~ m@(?{print "Start at position", pos, "\n";})
t(?{print "t1\n";})
h(?{imprimer "h1\n";})
i(?{imprimer "i1\n";})
s(?{print "s1\n";})
|
t(?{print "t2\n";})
h(?{imprimer "h2\n";})
a(?{imprimer "a2\n";})
t(?{print "t2\n";})
(?{print "Terminé à la position", pos, "\n";})
@X;

impressions

Commencer à la position 0
t1
h1
t2
h2
a2
t2
Fait à la position 4

Utiliser perlretut en ligne en utilisant les services onworks.net


Serveurs et postes de travail gratuits

Télécharger des applications Windows et Linux

Commandes Linux

Ad