syntaxe des masques

syntaxe des masques - - Fonctionnement des expressions régulières .

Description

La bibliothèque PCRE est un ensemble de fonctions qui implémentent la recherche par expressions régulières , en utilisant la même syntaxe et la même sémantique que le Perl 5 , avec quelques nuances ( voir ci-dessous ) . L ' implémentation actuelle est celle de Perl 5.005 .

Différences avec Perl

Les différences avec le Perl 5.005 sont présentée ici :

  1. Par défaut , un caractère d' espacement correspond à n'importe quel caractère que la fonction C isspace( ) reconnaît , bien qu'il soit possible de recompiler la bibliothèque PCRE avec d 'autres tables de caractères . Normalement , isspace( ) retourne TRUE pour les espaces , les retours chariot , les nouvelles lignes , les formfeed , les tabulations verticales et horizontales . Le Perl 5 n' accepte plus la tabulation verticale comme caractère d 'espacement . La séquence \v qui était dans la documentation Perl depuis longtemps n ' a jamais été reconnue . Cependant , la tabulation verticale elle-même était reconnue comme un caractère d' espacement jusqu la version 5.002 . Avec les version 5.004 et 5.005 , l' option \s l 'ignore .

  2. PRCE ne tolère pas la répétition de quantificateurs dans les expressions . Perl le permet , mais cela ne signifie pas ce que vous pourriez penser . Par exemple , ( ?!a){3 } ne s'interprète pas : les trois caractères suivants ne sont pas des "a " . En fait , cela s' interprète comme : le caractère suivant n'est pas "a " trois fois .

  3. Les occurrences de sous-masques qui interviennent dans des assertions négatives sont comptées , mais elles ne sont pas enregistrées dans le vecteur d ' occurrences . Perl modifie ses variables numériques pour toutes les occurrences de sous-masque , avant que l' assertion ne vérifie le masque entier , et uniquement si les sous-masques ne trouvent qu 'une seule occurrence .

  4. Bien que les caractères nul soient tolérés dans la chaîne de recherche , ils ne sont pas acceptés dans le masque , car le masque est utilisé comme une chaîne C standard , terminée par le caractère nul . Il faut donc utiliser la séquence d' échappement "\0 " dans le masque pour rechercher les caractères nul .

  5. Les séquence d ' échappement suivantes ne sont pas supportées par le Perl : \l , \u , \L , \U , \E , \Q . En fait , elles sont implémentées par la gestion intrinsèque de chaînes du Perl , et ne font pas partie de ses caractères spéciaux .

  6. L' assertion \G du Perl n'est pas supportée car elle n 'est pas pertinente pour faire des recherches avec des masques uniques .

  7. De manière assez évidente , PCRE n' accepte pas la construction ( ?{code} ) .

  8. Au moment de l' écriture de PCRE , Perl 5.005_02 avait quelques comportements étranges avec la capture des chaînes lorsqu 'une partie du masque est redoublée . Par exemple , " aba " avec le masque / ^(a(b) ?)+$ / va affecter à $2 la valeur "b" , mais la même manipulation avec "aabbaa " et / ^(aa(bb) ? )+$ / laissera $2 vide . Cependant , si le masque est remplacé par / ^( aa(b(b)) ?)+$ / alors $2 (et d'ailleurs $3 ) seront correctement affectés . Avec le Perl 5.004 , $2 sera correctement affecté dans les deux cas , et c ' est aussi vrai avec PCRE . Si Perl évolue vers un autre comportement cohérent , PCRE s ' adaptera probablement .

  9. Une autre différence encore non résolue est le fait qu' en Perl 5.005_02 le masque / ^(a) ?(?(1)a|b)+$ / accepte la chaîne "a" , tandis que PCRE ne l 'accepte pas . Cependant , que ce soit avec Perl ou PCRE / ^( a)?a / et "a " laisseront $1 vide .

  10. PCRE propose quelques extensions aux expressions régulières du Perl .

    1. ( a ) Bien que les assertions avec retour (lookbehind ) soit obligée d 'apparier une chaîne de longueur fixe , toutes les assertions avec retour peuvent avoir une longueur différente . Perl 5.005 leur impose d ' avoir toutes la même longueur .

    2. ( b ) Si PCRE_DOLLAR_ENDONLY est activé , et que PCRE_MULTILINE n'est pas activé , le méta caractère $ ne s'applique qu la fin physique de la chaîne , et non pas avant les caractères de nouvelle ligne .

    3. ( c ) Si PCRE_EXTRA est activé , un antislash suivi d 'une lettre sans signification spéciale est considérée comme une erreur .

    4. ( d ) SI PCRE_UNGREEDY est activé , la "gourmandise " des quantificateurs de répétition est inversées , ce qui est rend non gourmand par défaut , mais s 'ils sont suivis de ? , il seront gourmands .





Détails sur les expressions régulières

Introduction

La syntaxe et la sémantique des expressions régulière supportées par PCRE sont décrites ci-dessous . Les expressions régulières sont aussi décrites dans la documentation Perl , et dans un grand nombre d ' autres livres , avec de nombreux exemples . Jeffrey Friedl' s "Mastering Regular Expressions" , édité chez O'Reilly (ISBN 1-56592-257-3 ) , les décrits en profondeur . Cette description est organisée comme une documentation de référence .

Une expression régulière est un masque , appliqué à une chaîne sujet , de gauche à droite . La plupart des caractères se représentent eux-mêmes . Un exemple trivial : un masque qui serait " Le rapide renard gris " , pourra correspondre à une partie de la chaîne sujet qui sera identique au masque , comme par exemple " Le rapide renard gris court dans la forêt " ,

Méta-caractères

La puissance des expressions régulières provient de leur capacité à autoriser des alternatives et des quantificateurs de répétition dans le masque . Ils sont encodés dans le masque par des méta-caractères , qui ne représentent pas ce qu' ils sont , mais sont interprétés d 'une certaine manière .

Il y a deux sortes de méta-caractères : ceux qui sont reconnus n ' importe dans un masque , hormis entre crochets , et ceux qui sont reconnus entre crochets .

A l ' extérieur des crochets , les méta caractères sont :

/ antislash

Caractère d ' échappement , avec de multiples usages

^ Accent circonflexe

Le début de la chaîne sujet ( ou de ligne , en mode multiligne )

$ Dollar

La fin de la chaîne sujet ( ou de ligne , en mode multiligne )

. Point

Remplace n' importe quel caractère , hormis le caractère de nouvelle ligne (par défaut ) ;

[ Crochet ouvrant

Caractère de début de définition de classe

] Crochet fermant

Caractère de fin de définition de classe

| Barre verticale

Caractère de début d ' alternative

( Parenthèse ouvrante

Caractère de début de sous-masque

) Parenthèse fermante

Caractère de fin de sous-masque

? Point d'interrogation

Etend le sens de ( ; quantificateur de 0 ou 1 ; quantificateur de minimisation

* Etoile

Quantificateur de 0 ou plus

+ Plus

Quantificateur de 1 ou plus

{ Accolade ouvrante

Caractère de début de quantificateur minimum / maximum

} Accolade fermante

Caractère de fin de quantificateur minimum / maximum



La partie du masque qui est entourée de crochet et appelé une classe de caractères . Dans les classes de caractères , les seuls méta caractères autorisés sont :

\ Antislash

Caractère d ' échappement , avec de multiples usages

^ Accent circonflexe

Négation de la classe , mais uniquement si placé tout au début de la classe

- Moins

Indique un intervalle de caractères

] Crochet fermant

Termine la classe de caractères

La section suivante décrit l'utilisation de chaque méta-caractères.

Antislash

Le caractère antislash a de nombreuses utilisations .

En premier lieu , s' il est suivi d 'un caractère non alpha-numérique , il ne prendra pas la signification spéciale qui y est rattachée . Cette utilisation de l' antislash comme caractère d'échappement s'applique à l'intérieur et à l 'extérieur des classes de caractères . Par exemple , pour recherche le caractère étoile " * " , il faut écrire dans le masque : " \* " . Cela s ' applique dans tous les cas , que le caractère qui suive soit un méta-caractère ou non . C' est un moyen sûr pour s'assurer qu 'un caractère sera recherché pour sa valeur littérale , plutôt que pour sa valeur spéciale . En particulier , pour rechercher les antislash , il faut écrire : " \\ " .

Si un masque est utilisé avec l' option PCRE_EXTENDED , les espaces blancs du masque , mais qui ne sont pas dans une classe de caractères , et les caractères entre dièses " # " , ainsi que les nouvelles lignes sont ignorées . L ' antislash peut être utilisé pour échapper et ainsi rechercher un espace ou un dièse .

La deuxième utilité de l ' antislash est de pouvoir coder des caractères invisibles dans les masques . Il n ' y a pas de restriction sur la place de ces caractères invisibles , hormis pour le caractère nul qui doit terminer le masque .

Lors de la préparation du masque , il est souvent plus pratique d' utiliser les séquences d'échappement suivantes , plutôt que le caractère binaire qu 'elle représente :

\a

alarme , c' est-à-dire le caractère BEL (hex 07 )

\cx

" control-x" , avec x qui peut être n 'importe quel caractère .

\n

nouvelle ligne ( hex 0A )

\r

retour chariot ( hex 0D )

\t

tabulation ( hex 09 )

\xhh

caractère en hexadécimal , de code hh

\ddd

caractère en octal , de code ddd , ou référence arrière



Dans la séquence " \cx " si " x " est en minuscule , il est converti en majuscule . Puis , le bit 6 ( hex 40 ) est inversé . Ainsi " \cz " devient 1A , mais " \c { " devient hex 3B , tandis que " \c ; " devient hex 7B .

Après " \x " , deux caractères hexadécimaeux sont lus (les lettres peuvent être en majuscule ou minuscule ) .

Après " \0 " , deux caractères octal sont lus . Dans chacun des cas , le méta-caractère tente de lire autant de caractère que possible . Ainsi la séquence " \0\x\07 " , sera comprise comme deux caractères nuls , suivi d'un caractère alarme (BEL ) . Assurez-vous que vous fournissez suffisamment de chiffres après le méta-caractère .

La gestion de la séquence " \y " , avec y 0 est plutôt compliquée . En dehors des caractères de classes , PCRE va lire y et tous les caractères qui suivent comme des chiffres décimaux . Si y est plus petit que 10 , ou bien s ' il y a déjà eu au moins autant de parenthèses ouvrantes auparavant , la séquence est prise pour une référence arrière . Le détail sera vu ultérieurement , après la section sur les sous-masques .

A l' intérieur d'un caractère de classe , ou si y est plus grand que 10 , et qu'il n'y a pas eu assez de parenthèses ouvrantes auparavant , PCRE lis jusqu'à 3 chiffres octals à la suite de l 'antislash , et génère un octet unique , à partir des 8 bits de poids faible de la séquence . Tous les chiffres qui suivent ne sont pas interprétés , et se representent eux-mêmes . Par exemple :

\040

une autre manière d ' écrire un espace

\40

identique , dans la mesure il n ' y a pas 40 parenthèses ouvrantes auparavant

\7

est toujours une référence arrière

\11

peut être une référence de retour , ou une tabulation

\011

toujours une tabulation

\0113

est une tabulation suivi du caractère " 3 "

\113

est le caractère 113 ( étant donné qu'il ne peut y avoir plus de 99 références arrières )

\377

est un octet dont tous les bits sont à 1

\0113

peut être soit une référence arrière , soit le caractère NULL , suivi des caractères " 8 " et "1 "



Les valeurs octales supérieures ou égales à 100 ne doivent pas être introduites par un 0 , car seuls les trois premiers octets seront lus .

Toutes les séquences qui définissent une valeur d' un seul octet peuvent être utilisé dans les classes de caractères , et à l 'extérieur . De plus , dans une classe de caractères , la séquence " \b " est interprétée comme un caractère effacer (backspace , hex 08 ) . A l' extérieur d'une classe de caractères , il peut avoir d'autres significations (voir ci-dessous ) .

On peut encore se servir de l ' antislash pour préciser des types génériques de valeurs :

\d

tout caractère décimal

\D

tout caractère qui n ' est pas un caractère décimal

\s

tout caractère blanc

\S

tout caractère qui n ' est pas un caractère blanc

\w

tout caractère de " mot "

\W

tout caractère qui n' est pas un caractère de "mot "



Chaque paire précédente définit une partition de la table des caractères : les deux ensembles sont disjoints . Un caractère satisfera soit un méta-caractère , soit l ' autre .

Un caractère de " mot " sera une lettre , un chiffre ou le caractère souligné , c'est-à-dire un caractère qui pourra être une partie d 'un mot Perl . La définition des lettres et chiffres est définie par les tables de caractères de PCRE , et peut varier suivant la table locale de caractère ( voir "Tables de caractères locales " , ci-dessus . Par exemple , dans la configuration français ( "fr" ) , certains caractères ont des codes supérieurs à 128 , pour les caractères accentués , et ils seront compris par le méta caractère \w .

Ces séquences de caractères peuvent apparaître à l' intérieur ou à l 'extérieur des classes de caractères . Elles remplacent à chaque fois un caractère du type correspondant . Si cette séquence est placée en fin de masque , et qu' il n 'y a plus de caractère à comparer dans la chaîne sujet , la recherche échoue .

La quatrième utilisation de l' antislash intervient lors d 'assertions simples . Une assertion impose une condition à un certain point , sans remplacer de caractère . L ' utilisation de sous-masques pour réaliser des assertions plus complexes est décrites plus-bas . Les assertions avec antislash sont les suivantes :

\b

limite de mot

\B

pas limite de mot

\A

début de la chaîne sujet ( indépendant du mode multi-lignes )

\Z

fin de la chaîne sujet ou nouvelle ligne à la fin de la chaîne sujet ( indépendant du mode multi-lignes )

\z

fin de la chaîne sujet ( indépendant du mode multi-lignes )



Ces assertions ne peuvent pas apparaître dans une classe de caractères ( mais "\b " a une autre signification à l'intérieur d'une classe de caractères ) .

Une limite de mot est un emplacement dans la chaîne sujet ou un caractère et son suivant ne sont pas en même temps des caractères de mot , ou le contraire ( on peut le voir comme \w\W ou \W\w ) , ou encore le premier ou le dernier caractère est un caractère mot .

Les assertions \A , \Z , et \z diffèrent des méta caractères ^ et $ dans la mesure ils ne sont pas dépendants des options , notamment PCRE_NOTBOL ou PCRE_NOTEOL . La différence entre \Z et \z tient au fait que \Z recherche les positions avant les nouvelles lignes et à la fin de la chaîne sujet , tandis que \z ne recherche que la fin de la chaîne .

Accent circonflexe et Dollar

En dehors d' une classe de caractères , avec les options par défaut , ^ est une assertion qui n 'est vraie que si elle est placée tout au début de la chaîne . A l' intérieur d'une classe de caractères , ^ a un tout autre sens (voir ci-dessous ) .

^ n' a pas besoin d 'être le premier caractère du masque , si plusieurs alternatives sont proposées , mais il doit être placé en premier dans chaque alternative . Si toutes les alternatives commencent par ^ , alors le masque est dit ancré ( il y a une autre construction qui porte cette appellation ) .

$ est une assertion qui n ' est vraie que si elle est placée tout en fin de chaîne ou juste avant un caractère de nouvelle ligne qui serait le dernier caractère de la chaîne . A l' intérieur d'une classe de caractères , $ a un tout autre sens (voir ci-dessous ) .

$ n' a pas besoin d 'être le dernier caractère du masque , si plusieurs alternatives sont proposées , mais il doit être placé en dernier dans chaque alternative . Si toutes les alternatives finissent par $ , alors le masque est dit ancré ( il y a une autre construction qui porte cette appellation) . $ n 'a pas de valeur particulière dans une classe de caractères .

La signification de $ peut changer , de manière à l' amener à ce qu'il ne puisse se trouver qu 'en toute fin de la chaîne sujet . Cela se fait en ajoutant l' option PCRE_DOLLAR_ENDONLY au moment de la compilation , ou de l 'exécution . Cette option est inopérante sur \Z .

La signification de ^ peut changer , de manière à l' amener à ce qu'il puisse se trouver immédiatement avant et immédiatement après un caractère de nouvelle ligne " \n " . Cela se fait en ajoutant l' option PCRE_MULTILINE au moment de la compilation ou de l 'exécution . Par exemple , le masque / ^abc$ / accepte la chaîne " def\nabc " uniquement en mode multi-lignes . Par conséquent , toutes les parties du masques qui commencent par " ^ " ne sont pas ancrées , en mode multi-lignes . L' option PCRE_DOLLAR_ENDONLY est ignorée si l 'option PCRE_MULTILINE est choisie .

Notez que les méta caractères \A , \Z , et \z peuvent servir à répérer le début et la fin du sujet , et toutes les parties du masque qui commenceront par \A seront toujours ancrées , avec l ' option PCRE_MULTILINE ou non .

Point

En dehors d' une classe de caractères , un point remplace n'importe quel caractère , même invisible et à l 'exception du caractère de nouvelle ligne . Avec l' option PCRE_DOTALL le point remplace n 'importe quel caractère , même le caractère de nouvelle ligne . La gestion des points et complètement indépendante de ^ et $ . Le seul point commun est que les deux ont un comportement particulier vis à vis des caractère de nouvelle ligne .

Le point n ' a pas de comportement particulier dans une classe de caractères .

Crochets

Un crochet ouvrant [ introduit une classe de caractères , et le crochet fermant ] la conclut . Le crochet fermant n ' a pas de signification en lui-même . Si le crochet fermant est nécessaire à l' intérieur d'une classe de caractères , il faut qu'il soit le premier caractère (après un ^ éventuel ) ou échappé avec un antislash .

Une classe de caractères remplace un seul caractère dans la chaîne sujet , à moins que le premier caractère de la classe soit un accent circonflexe ^ , qui représente une négation : le caractère ne doit pas se trouver dans la classe . Si ^ est nécessaire dans la classe , il suffit qu' il ne soit pas le premier caractère , ou bien qu 'il soit échappé avec un antislash .

Par exemple , le caractère [ aeiou ] remplace n'importe quelle voyelle minuscule , tandis que [^aeiou ] remplace n'importe quelle caractère qui n'est pas une voyelle minuscule . ^ est une notation pratique pour spécifier des caractères qui sont dans une classe , en ne citant que ceux qui n 'y sont pas . Le comportement est inchangé .

Avec l' option d'insensibilité à la casse , toutes les lettres d 'une classe de caractères représentent en même temps la majuscule et la minuscule . Par exemple , [ aeiou ] représentera " A " ou " a " , et [^aeiou ] n'acceptera pas ni " A " , tandis que sans l'option , elle l 'accepterait .

Le caractère de nouvelle ligne n' est pas traité de manière spéciale dans les classes de caractères , quelque soit l 'option PCRE_DOTALL ou PCRE_MULTILINE . Une classe telle que [ ^a ] acceptera toujours une nouvelle ligne .

Le signe moins ( - ) est utilisé pour spécifier un intervalle de caractères , dans une classe . Par exemple , [ d-m ] Par exemple , [d-m ] remplace toutes les lettres entre d et m inclus . Si le caractère moins est requis dans une classe , il faut l' échapper avec un antislash , ou le faire apparaître à une position ou il ne pourra pas être interprété comme une indication d'intervalle , c 'est-à-dire au début ou à la fin de la classe .

Il n' est pas possible d'avoir le caractère crochet fermant " ] " comme fin d 'intervalle . Un masque tel que [ W -]46 ] est compris comme la classe de caractères contenant deux caractères ("W " et " -" ) suivi de la chaîne littérale "46]" , ce qui fait qu'il va accepter " W46 ] " ou " -46 ] " . Cependant , si " ] " est échappé avec un antislash , le masque [W-\]46 ] est interprété comme une classe d 'un seul caractère , contenant un intervalle de caractères .

La valeur octale ou hexadécimale de " ] " peut aussi être utilisée pour déterminer les limites de l 'intervalle . Les intervalles travaillent sur des séquences ASCII . Ils peuvent aussi être précisées avec des valeurs numériques , par exemple " [\000-\037 ] " . Si cet intervalle inclut des lettres utilisées avec une option d ' insensibilité de casse , les majuscules ou minuscules correspondantes seront aussi incluses . Par exemple , " [C-c ] " est équivalent é " [][\^_`wxyzabc ] " , avec l'option d 'insensibilité de casse . Si la table locale de caractères est " fr" , " [\xc8-\xcb ] " correspond aux caractères accentués .

Les types de caractères \d , \D , \S , \s , \w , \W peuvent aussi intervenir dans les classes de caractères . Par exemple , " [][\^_`wxyzabc][\dABCDEF ] " acceptera n 'importe quel caractère hexadécimal . Un accent circonflexe peut aussi être utilisé pour spécifier adroitement des ensembles de caractères plus restrictifs : par exemple [ ^\W_ ] accepte toutes les lettres et les chiffres , mais pas les soulignés . Tous les caractères non alpha - numériques autres que \ , - , ^ ( placés en début de chaîne ) et ] n 'ont pas de signification particulière , mais ils ne perdront rien à être échappés .

Barre verticale

La barre verticale | sert à séparer des alternatives . Par exemple , dans le masque " / dupont|martin / " recherche soit " dupont " , soit " martin " . Le nombre d' alternatives n'est pas limité , et il est même possible d 'utiliser la chaîne vide . Lors de la recherche , toutes les alternatives sont essayées , de gauche à droite , et la première qui est acceptée est utilisée .

Si les alternatives sont dans un sous-masque , elle ne réussiront que si le masque principal réussi aussi .

Options internes

Les options PCRE_CASELESS , PCRE_MULTILINE , PCRE_DOTALL et PCRE_EXTENDED peuvent être changée à l' intérieur du masque lui-même , avec des séquences mises entre " ( ? " et " ) " . Les options sont :

i

PCRE_CASELESS

m

PCRE_MULTILINE

s

PCRE_DOTALL

x

PCRE_EXTENDED

Par exemple, (?im) rend le masque insensible à la casse, et multi-lignes. Il est possible d'annuler ces options en les faisant précéder par un signe - : par exemple (?im-sx) , ajoutera les options PCRE_CASELESS et PCRE_MULTILINE mais annulera les options PCRE_DOTALL et PCRE_EXTENDED . Si une option apparaît avant et après le signe moins, l'option sera annulée.

Le domaine d' application de ces options dépend de la position de la séquence d 'option . Pour toutes les séquences d' options qui sont hors des sous-masques (définis plus loin) , l'effet est le même que si l 'option avait été fixée dès le début de la recherche . Les exemples suivants se comportent tous de la même façons : ( ?i)abc , a(?i)bc , ab(?i)c , abc(?i ) , et sont parfaitement équivalents au masque abc avec l 'option PCRE_CASELESS . En d' autres termes , activer des séquences d'options dans le corps principal du masque revient à appliquer l 'option à tout le masque , sauf ordre contraire dans les sous-masques . S' il y a plusieurs séquences d'options qui portent sur la même option , la dernière s 'appliquera .

Si une option intervient dans un sous-masque , le comportement est différent . C ' est un changement de comportement apparu en Perl 5.005 . Une option à l' intérieur d'un sous-masque n'affecte que cette partie du masque , ce qui fait que (a(?i)b)c acceptera abc et aBc mais aucune autre chaîne (en supposant que PCRE_CASELESS n'est pas utilisé ) . Cela signifie que les options permettent d ' avoir différente configuration de recherche pour différentes parties du masque .

Une séquence d' options dans une alternative affecte toute l 'alternative . Par exemple : ( a(?i)b|c ) accepte " ab " , " aB " , " c " , et " C " , même si , comme dans le cas de " C " , la première alternative qui porte l'option n 'est pas prise en compte . Sinon , cela risque d ' introduire des comportements très étranges : les options spécifiques à PCRE telles que PCRE_UNGREEDY et PCRE_EXTRA peuvent être modifiées de la même manière , en utilisant respectivement les caractères U et X . L' option (?X ) est particulière , car elle doit toujours intervenir avant toutes les autres options , même au niveau du masque entier . Il vaut mieux l ' activer au début du masque .

Sous-masques

Les sous-masques sont délimités par des parenthèses , et peuvent être imbriquées . Ajouter des sous-masques a deux utilités :

Délimiter des alternatives . Par exemple , le masque char( don|mant| ) acceptera les mots " char " , " charmant " , ou " charmant " . Sans les parenthèses , il n' accepterait que " chardon " , " mant " ou la chaîne vide " " .

Le sous-masque est considéré comme capturant : lorsqu' une chaîne sujet est acceptée par le masque complet , les sous-masques sont transmis à l 'appelant grâce à un vecteur de sous-masques . Les parenthèses ouvrantes sont comptées de gauche à droite , ( commençant à 1 ) . Par exemple , soit la chaîne sujet " le roi soleil " qui est utilisée avec le masque suivant : Le ( (roi|prince ) (soleil|charmant) ) les sous-masques capturé sont " roi soleil " , " roi " , et " soleil " , numérotés respectivement 1 , 2 , et 3 .

L' ubiquité des parenthèses n'est pas toujours simple d 'emploi . Il y a des moments regrouper des sous-masques est nécessaire , sans pour autant capturer la valeur trouvée . Si une parenthèse ouvrante est suivie de " ? : " , le sous-masque ne capture pas la chaîne assortie , et ne sera pas compté lors de la numérotation des captures . Par exemple , avec la chaîne " le prince charmant " , utilisé avec le masque Le ( ( ?roi|prince ) (soleil|charmant) ) les chaînes capturées seront " prince charmant " et " charmant " , numérotés respectivement 1 et 2 .

Le nombre maximal de chaîne capturées est de 99 , et le nombre total de sous-masque ( capturant ou non ) ne doit pas dépasser 200 .

( ?i:samedi|dimanche ) et (? :(?i ) samedi | dimanche ) : De plus , comme les séquences d' options sont valables sur toute une alternative , les masques ci-dessus accepteront aussi bien "DIMANCHE " que "Dimanche " .

Répétitions

Les répétitions sont spécifiées avec des quantificateurs , qui peuvent être placés à la suite des caractères suivants :

a

Un caractère unique , même s' il s'agit d 'un méta caractère

[abc]

Une classe de caractères

\2

Une référence de retour ( Voir section suivante )

(a|b|c)

Un sous-masque avec parenthèses ( à moins que ce ne soit une assertion , voir plus loin )



Les quantificateurs généraux précisent un nombre minimum et maximum de répétitions possibles , donnés par deux nombres entre accolades , et séparés par une virgule . Ces nombres doivent être plus petits que 65536 , et le premier nombre doit être égal ou inférieur au second . Par exemple z{ 2,4 } accepte " zz " , " zzz " , ou " zzzz " . L' accolade fermante n 'a pas de signification par elle-même .

Si le second nombre est omis , mais que la virgule est , cela signifie qu' il n 'y a pas de limite supérieure . Si le second nombre et la virgule sont omis , le quantificateur correspond au nombre exact de répétition attendues . Par exemple : accepte n' importe quelle succession d'au moins 3 voyelles minuscules , tandis que \d{d } n 'accepte que 8 chiffres exactement .

Une accolade ouvrante qui apparaît à une position un quantificateur n' est pas accepté , ou si la syntaxe des quantificateurs n 'est pas respectée , sera considérée littérale . Par exemple , " {,6 } " n 'est pas un quantificateur , mais une chaîne de 4 caractères .

Le quantificateur { 0 } est autorisé , mais l 'expression est alors ignorée .

*

équivalent à { 0 , }

+

équivalent à { 1 , }

?

équivalent à { 0,1 }



Il est possible de constituer des boucles infinies en créant un sous-masque sans caractères , mais pourvu d ' un quantificateur sans limite supérieure . Par exemple " (a ? )* .

Les versions plus anciennes de Perl et PCRE généraient alors une erreur au moment de la compilation . Cependant , étant donné qu ' il existe des situations ces constructions peuvent être utiles , ces masques sont désormais autorisés . Cependant , si la répétion du sous-masque ne trouve aucun caractère , la boucle est interrompue .

Par défaut , les quantificateurs sont dits " gourmands" , c'est à dire , qu'ils cherchent d 'abord à trouve le nombre maximal de répétitions qui autorise le succès de la recherche . L' exemple classique posé par cette gourmandise est la recherche de commentaires d 'un programme en C . Les commentaires apparaissent entre les séquences / *....* / et à l ' intérieur de ces délimiteurs , les * et / sont autorisés . Appliquer le masque / \*.*\* / à la chaîne / * first commet * / not comment / * second comment * / ne peut réussir , car le masque travaille sur toute la chaîne , à cause de la gourmandise du caractère .* .

Cependant , un quantificateur suivi d' un point d'interrogation cesse d 'être gourmand , et au contraire , ne recherche que le nombre minimum de répétition . Dans ces conditions , le masque / \*.*?\* / Dans ces conditions , le masque / \*.*?\* / trouvera bien les commentaires du code C . La signification des autres quantificateurs n ' est pas changée .

Attention à ne pas confondre l' utilisation du point d 'interrogation ici avec son utilisation comme quantificateur lui-même . A cause cette ambiguité , il peut apparaître des situations il faut le doubler : \d??\d . Ce masque va tenter de lire un seul chiffre , mais le cas échéant , il acceptera 2 chiffres pour permettre à la recherche d ' aboutir . Si l' option PCRE_UNGREEDY est activée , (une option qui n'est pas disponible avec Perl ) alors les quantificateurs sont non gourmand par défaut , mais peuvent être rendu gourmand au cas par cas , en ajoutant un point d 'interrogation après . En d ' autres termes , cette option inverse le comportement par défaut .

Lorsqu ' un sous-masque est quantifié avec un nombre minimum de répétitions , qui soit plus grand que 1 , ou avec un maximum de répétitions , le masque compilé aura besoin de plus de place de stockage , proportionnellement au minimum et au maximum .

Si un masque commence par ..* ou .{ 0 , } et que l'option PCRE_DOTALL (équivalent en Perl à / s ) est activée , c 'est-à-dire en autorisant le remplacement des nouvelles lignes par un méta-caractère , alors le masque est implicitement ancré , car tout ce qui suit va être mangé par la première séquence , et se comportera comme si le masque se terminait par le méta caractère \A . Dans le cas on sait d' avance qu'il n'y aura pas de caractère de nouvelle ligne , activer l'option PCRE_DOTALL et commencer le masque par .* permet d 'optmiser le masque .

Alternativement , on peut utiliser ^ pour ancrer explicitement le masque . Lorsqu ' un sous-masque capturant est répété , la valeur capturée est la dernière . Par exemple , après que " (inter[net]{3}\s*) + " ai été appliqué à " internet interne " , la valeur de la chaîne capturée est " interne " .

Cependant , s' il y a des sous-masques imbriqués , la valeur capturée correspondante peut l 'avoir été lors des précédentes itérations . Par exemple : / ( a|(b))+ / accepte " aba " et la deuxième valeur capturée est " b " .

Références arrières

En dehors des classes de caractères , un antislash suivi d' un nombre plus grand que 0 (et possiblement plusieurs chiffres ) est une référence arrière (c'est à dire vers la gauche ) dans le masque , en supposant qu 'il y ait suffisamment de sous-masques capturants précédants .

Cependant , si le nombre décimal suivant l' antislash est plus petit que 10 , il sera toujours considéré comme une référence arrière , et cela génèrera une erreur si le nombre de capture n 'est pas suffisant . En d' autres termes , il faut qu 'il existe suffisamment de parenthèses ouvrantes à gauche de la référence , surtout si la référence est inférieure à 10 .

Reportez-vous à la section " antislash " pour avoir de plus amples détails à propos du nombre de chiffres qui suivent l 'antislash .

La référence arrière remplace ce qui a été capturé par un sous-masque dans le masque courant , plutôt que remplace le sous-masque lui-même . Ainsi ( calme|rapide ) et \1ment trouvera " calme et calmement " et " rapide et rapidement " , mais pas " calme et rapidement " . Si la recherche tient compte de la casse , alors la casse de la chaîne capturée sera importante . Par exemple , ( (?i)rah)\s+\1 trouve " rah rah " et " RAH RAH " , mais pas " RAH rah " , même si le sous-masque capturant initial ne tenait pas compte de la casse .

Il peut y avoir plusieurs références arrières dans le même sous-masque . Si un sous-masque n ' a pas été utilisé dans une recherche , alors les références arrières échoueront . Par exemple " (a|(bc))\2 " ne réussira jamais si la chaîne sujet commence par " a " plutôt que par " bc " .

Etant donné qu' il peyt y avoir jusqu'à 99 références arrières , tous les chiffres après l 'antislash sont considérés comment faisant potentiellement partie de la référence arrière . Si le masque recherche un chiffre après la référence , alors il faut impérativement utiliser des délimiteurs pour terminer la référence arrière .

Si l ' option PCRE_EXTENDED est activée , on peut utiliser un espace . Sinon , un commentaire vide fait l ' affaire . Une référence arrière qui intervient à l ' intérieur de parenthèses auquel elle fait référence échouera dès que le sous-masque sera utilisé . Par exemple , ( a\1 ) Par exemple , (a\1 ) échouera toujours . Cependant , ces références peuvent être utiles dans les sous-masques répétitifs . Par exemple , le masque " (a|b\1) + " pourra convenir pour " a " , " aba " , " ababaa " , etc... .

A chaque itération du sous-masque , la référence arrière utilise le résultat du dernier sous-masque . Pour que cela fonctionne , il faut que la première itération n' ai pas besoin d 'utiliser la référence arrière . Cela arrive avec les alternatives , comme dans l ' exemple ci-dessus , ou avec un quantificateur de minimum 0 .

Assertions

Une assertion est un test sur les caractères suivants ou précédent celui qui est en cours d ' étude . Ce test ne consomme par de caractère ( ie , on ne déplace pas le pointeur de caractères ) . Les assertions simples sont codées avec \b , \B , \A , \Z , \z , ^ et $ , et sont décrites précédemment .

Il existe cependant un type d ' assertions plus complexes , codées sous la forme de sous-masques . Il en existe deux types : celles qui travaillent au-delà de la position courante ( \w+(?= ; ) ) , et celles qui travaillent en deça ( (? !)\w + ) .

Une assertion se comporte comme un sous-masque , hormis le fait qu ' elle ne déplace pas le pointeur de position . Les assertions avant commencent par ( ?= pour les assertions positives , et par (? ! , pour les assertions négatives . Par exemple : \w+( ?= ; ) s'assure qu'un mot est suivi d'un point-virgule , mais n 'inclus pas le point virgule dans la capture . D' autre part , (?!foo)bar en est proche , mais ne trouve pas une occurrence de " bar " qui soit précédée par quelque chose d'autre que " foo foo" ; il trouve toutes les occurrences de " bar " , quelque soit ce qui le précéde , car l'assertion (?!foo ) est toujours vraie quand les trois caractères suivants sont " bar " . Une assertion arrière est ici nécessaire .

Les assertions arrières commencent par ( ? = pour les assertions positives , et ( ? ! pour les assertions négatives . Par exemple : ( ? !foo)bar trouve les occurrences de " bar " qui ne sont pas précédées par " foo " .

Le contenu d' une référence arrière est limité de telle façon que les chaînes qu 'il utilise soient toujours de la même taille . Cependant , lorsqu' il y a plusieurs alternatives , elles n'ont pas besoin d 'être de la même taille . Par exemple , ( ? =bullock|donkey ) est autorisé , tandis que ( ? !dogs ?|cats ? ) provoque une erreur de compilation . Les alternatives qui ont des longueurs différentes ne sont autorisées qu ' au niveau supérieur des assertions arrières . C' est une amélioration du fonctionnement de Perl 5.005 , qui impose aux alternatives d 'avoir toutes la même taille . Une assertion telle que ( ? =ab(c|de) ) n'est pas autorisée , car l'assertion de bas niveau (la deuxième , ici ) a deux alternatives de longueurs différentes . Pour la rendre acceptable , il faut écrire ( ? =abc|abde )

L' implémentation des assertions arrières déplace temporairement le pointeur de position vers l'arrière , et cherche à vérifier l 'assertion . Si le nombre de caractères est différent , la position ne sera pas correcte , et l ' assertion échouera . La combinaison d ' assertions arrières avec des sous-masques peut être particulièrement pratique à fin des chaînes . Un exemple est donné à la fin de cette section .

Plusieurs assertions peuvent intervenir successivement . Par exemple , le masque ( ? =\d{3})( ? !999)foo recherche les chaînes " foo " précédées par trois chiffres qui ne sont pas "999 " . Notez que chaque assertion est appliquées indépendemment , au même point de la chaîne à traiter . Tout d' abord , il est vérifié que les trois premiers caractères ont tous des chiffres , puis on s'assure que ces trois caractères ne sont pas " 999 " . Le masque précédant n' accepte pas " foo " précédé de 6 caractères , les trois premiers étant des chiffres et les trois suivants étant différents de " 999 " . Par exemple , ce masque n' acceptera pas la chaîne " 123abcfoo " . Pour ce faire , il faut utiliser le masque suivant : ( ? =\d{3}.. .)( ? !999 )foo . Dans ce masque , la première assertion vérifie les six premiers caractères , s' assure que les trois premiers sont des entiers , et la deuxième assertion s'assure que les trois derniers caractères ne sont pas " 999 " .

De plus , les assertions peuvent être imbriquées : ( ? =( ? !foo)bar)baz recherche les occurrences de " baz " qui sont précédées par " bar " , qui , à son tour , n'est pas précédé par " foo " . Au contraire , ( ? =\d{3}(?!999).. .)foo est un autre masque , qui recherche les caractères " foo " , précédés par trois chiffres , suivis trois autres caractères qui ne forment pas " 999 " . Les assertions ne sont pas capturantes , et ne peuvent pas être répétées . Si une assertion contient des sous-masques capturants en son sein , ils seront compris dans le nombre de sous-masques capturants du masque entier . La capture est réalisée pour les assertions positives , mais cela n ' a pas de sens pour les assertions négatives .

200 assertions au maximum sont autorisées .

Sous-masques uniques

Avec les quantificateurs de répétitions , l' échec d'une recherche conduit normalement à une autre recherche , avec un nombre différent de répétitions , pour voir si le masque ne s'applique pas dans d 'autres conditions . Parfois , il est pratique d' éviter ce comportement , soit pour changer la nature de la recherche , soit pour la faire abandonner plus tôt , si on pense qu'il n'est pas besoin d 'aller plus loin .

Considérons par exemple , le masque \d+foo appliqué à la ligne 123456bar . Après avoir tenté d' utiliser les 6 chiffres suivi de " foo " qui font échouer , l'action habituelle sera de réessayer avec 5 chiffres , puis avec 4 , et ainsi de suite jusqu'à l 'échec final .

Un sous-masque évalué une seule fois permettrait d' indiquer que lorsqu'une partie du masque est trouvée , elle n'a pas besoin d 'être réévaluée à chaque tentative . Ceci conduirait à ce que la recherche échoue immédiatement après le premier test . Ces assertions ont leur propre notation , commençant avec ( ? comme ceci : ( ? \d+ )bar .

Ce type de parenthèses verrouille le sous-masque qu' il contient un fois qu'il a été trouvé , et empêche un échec ultérieur d 'y repasser , mais autorise à revenir plus loin en arrière . Une autre description est que les sous-masques de ce type recherche les chaînes de caractères , et les ancre le sous-masque à l ' intérieur de la chaîne .

Les sous-masques uniques ne sont pas capturants . Des cas simples comme ceux présentés ci-dessus peuvent être pris comme des situations maximisantes , qui réservent le maximum de caractères . En effet , alors que \d + et \d+ ? ajustent le nombre de chiffres trouvés de manière à laisser la possibilité au masque de réussir , ( ? \d+ ) ne peut retenir que la séquence entière de chiffres . Cette construction peut contenir un nombre arbitraire de sous-masques complexes , et ils peuvent être imbriqués .

Les sous-masques uniques ne peuvent être utilisés qu ' avec les assertions arrières , pour effectuer une recherche efficace en fin de chaîne . Considérons un masque simple tel que " abcd$ " appliqué à une très longue chaîne qui ne lui correspond pas . A cause du système de recherche de gauche à droite , PCRE va commencer par rechercher un " a " dans la chaîne sujet , puis vérifier si ce qui suit convient au reste du masque . Si le masque est spécifié sous la forme ^.*abcd$ alors , la séquence .* remplace en premier lieu la chaîne entière , et échoue , repart en arrière , et remplace tous les caractères sauf le dernier , échoue , retourne en arrière , prend un caractère de moins , etc.. . et ainsi de suite . Encore une fois , la recherche du " a " passe en revue toute la chaîne de gauche à droite , ce qui n 'est pas très efficace . Par contre , si le masque était écrit ^( ? .*)( ? =abcd ) alors il n 'y aurait pas de retour en arrière , pour satisfaire la séquence .* , car elle ne peut que remplacer toute la chaîne . L ' assertion arrière consécutive va alors faire un test sur les 4 derniers caractères . Si elle échoue , la recherche est immédiatement interrompue .

Pour les chaînes très longues , cette approche fait la différence en terme de performances et de temps de recherche . Lorsqu' un masque contient une répétition illimitée dans un sous-masque , qui contient lui-même un nombre illimité de répétiteur , l'utilisation des sous-masques à utilisation unique sont la seule façon d'éviter l 'échec de la recherche à après un temps de calcul trop long .

Le masque ( \D+ | \d + )*[! ? ] recherche un nombre illimité de sous-chaînes , qui contiennent soit des non-chiffres , soit des chiffres inclus dans , suivi soit par ! ou par ? . Lorsqu ' il trouve une solution , ce masque va très vite . Mais , lorsqu ' il est appliqué à une chaîne telle que : aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa , il lui faut beaucoup de temps pour annoncer un échec . Cela est au fait que la chaine peut être divisée en deux sous-chaînes d' un grand nombre de façons , et qu'elles ont toutes été essayées . (Cet exemple utilisait [! ? ] plutôt qu'un caractère simple , car PCRE et PHP utilise une optimisation qui leur permettent de détecter rapidement l'échec lorsqu 'un caractère unique est trouvé . Il se souvient du dernier caractère qui est attendu , et s' aperçoit rapidement qu'il n'y a pas ce caractère ) .

Si le masque utilisé est ( ( ? \D+) | \d + )*[! ? ] les séquences de chiffres ne peuvent pas être trouvées , et l 'échec intervient rapidement .

Les sous-masques conditionnels

Il est possible de lier un sous-masque à une condition , ou de choisir entre deux sous-masques alternatifs , en fonction du résultat d ' une assertion , ou suivant les résultats de recherche précédents .

Les deux formes possibles de sous-masques conditionnels sont ( ?(condition)masque positif ) et ( ?(condition ) masque positif | masque négatif ) .

Si les conditions sont satisfaites , le masque positif est utilisé , sinon , le masque négatif est utilisé , si présent . S ' il y a plus de deux alternatives , une erreur est générée à la compilation .

Il y a deux types de conditions : si le texte entre les parenthèses est une séquence de chiffres , alors la condition est satisfaite si le sous-masque correspondant à ce numéro a réussi . Considérons le masque suivant , qui contient des espaces non significatifs pour le rendre plus compréhensible ( on supposera l'option PCRE_EXTENDED activée ) et qui est divisé en trois parties pour simplifier les explications : ( \ ( ) ? [^()] + ( ?(1 ) \ ) ) .

La première partie recherche une parenthèse ouvrante optionnelle , et si elle existe , elle est capturée . La deuxième partie recherche un séquence de caractères qui ne contiennent pas de parenthèses . La troisième partie est conditionnée à la première , et s' assure que s 'il y avait une parenthèse ouvrante , il en existe une fermante . Si une parenthèse ouvrante a été trouvée , elle a été capturée , et donc la première capture existe , et la condition est exécutée . Sinon , elle est ignorée .

Ce masque recherche donc une séquence de lettres , éventuellement placées entre parenthèse . Si la condition n ' est pas une séquence de chiffres , il faut que ce soit une assertion . Ce peut être une assertion positive ou négative , arrière ou avant . Considérons le masque suivant ( même conditions que le précédent ) et avec deux alternatives en seconde ligne : ( ?(?=[^a-z]*[a-z])\d{2}[a-z]{3}-\d{2 } | \d{2}-\d{2}-\d{2 } ) . La condition est une assertion avant positive , qui recherche une séquence optionnelle de caractères non-lettre . En d' autres termes , elle teste la presence d 'au moins une lettre dans la chaîne sujet . Si une lettre est trouvée , la recherche se poursuit avec la première alternative , et sinon , avec la seconde . Ce masque recherche des chaînes de la forme dd-aaa-dd ou dd-dd-dd , avec " aaa " qui sont des lettres , et dd qui sont des chiffres .

Commentaires

La séquence ( ?# marque le début d 'un commentaire , qui se termine à la prochaine parenthèse fermante . Les parenthèses imbriquées ne sont pas autorisées . Les caractères entre ces délimiteurs ne jouent alors aucun rôle dans le masque .

Si l' option PCRE_EXTENDED est activée , les caractères dièses # non échappés en dehors d'une classe de caractères introduisent un commentaire qui continuera jusqu la prochaine ligne dans le masque .

Masques récursifs

Considérons le cas il faut recherche dans une chaîne , avec un niveau d ' imbrications infini de parenthèses . Sans l' aide de la récursivité , le mieux que nous puissions obtenir est de créer un masque avec un niveau fixé de profondeur d 'imbrication . Il n' est pas possible de traiter des masques à niveau d 'imbrications variable . PCRE fournit un nouvel outil expérimental qui permet d' utiliser la récursivité dans les masques (entre autre ) . L' option (?R ) est fournie pour servir la cause de la récursivité . Le masque suivant résoud le problème des parenthèses ( l'option PCRE_EXTENDED est utilisée pour ignorer les espaces ) : \ ( ( ( ? [^()]+ ) | (?R ) )* \ )

Tout d ' abord , le masque recherche une parenthèse ouvrante . Puis , il recherche n' importe quel nombre de sous-chaînes qui sont soit des séquences de caractères non-parenthèses , ou bien une recherche récursive avec le même masque (i.e . une chaîne correctement incluse entre parenthèses ) . Finalement , il recherche une parenthèse fermante .

Cet exemple particulier contient un nombre illimité de répétitions imbriquées , ce qui fait que l' utilisation de sous-chaînes à utilisation unique pour rechercher les séquence de caractères non-parenthèses est important , lorsqu'il s'applique à une chaîne qui n 'est pas valide . Par exemple , si on l' applique à " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa( ) " la réponse arrive rapidement . Sinon , si les sous-chaînes à utilisation unique ne sont pas utilisées , la recherche peut prendre un très long temps , car il existe de très nombreuses combinaisons de + et * à tester avant de conclure à l ' échec .

Les valeurs utilisées pour capturer les sous-masques sont celles utilisées par les niveaux les plus hauts de récursivités , auquel la valeur est fixée . Si le masque précédent est utilisé avec ( ab(cd)ef ) la valeur de la parenthèse capturante est " ef " , qui est la dernière valeur lue au niveau supérieur . Si de nouvelles parenthèses sont ajoutées , par exemple : \( ( ( ( ? [^()]+ ) | (?R ) )* ) \ ) alors la chaîne capturée est " ab(cd)ef " , c 'est-à-dire le contenu de la parenthèses capturant de plus haut niveau . S ' il y a plus de 15 parenthèses capturantes dans une chaîne , PCRE doit utiliser plus de mémoire pour stocker ces données . S' il ne peut obtenir cette mémoire supplémentaire , il ne fait que sauver les 15 premières , car il n'y a pas moyen de générer une erreur de mémoire lors d 'une récursion .

Performances

Certaines séquences de recherches sont plus efficaces que d ' autres . Ainsi , il est plus efficace d' utiliser une classe de caractères telle que [aeiou ] plutôt qu'une alternative (a|e|i|o|u ) .

En général , le masque le plus simple , qui permette la recherche désirée est le plus efficace . Le livre de Jeffrey Friedl' s contient de nombreuses études à propos de l 'optimisation des expressions régulières .

Lorsqu' un masque commence par.* et que l'option PCRE_DOTALL est activée , le masque est implicitement ancré par PCRE , étant donné qu 'il ne peut que rechercher au début de la chaîne . Cependant , si option PCRE_DOTALL n' est pas activée , PCRE ne peut faire aucune optimisation car le méta-caractères point " . " ne remplace pas une nouvelle ligne , et si la chaîne sujet contient des nouvelles lignes , le masque peut trouver une solution qui serait située juste après une de ces nouvelles lignes , et non pas seulement au début de la chaîne sujet . Par exemple , le masque , ( .*)second acceptera la chaîne " premier \net second " (avec " \n " qui remplace la nouvelle ligne) , et la première chaîne capturée sera " et " .

Afin d' effectuer la recherche , PCRE va essayer d 'appliquer le masque à partir de chaque début de ligne . Si vous utilisez un tel masque avec des chaînes qui ne contiennent pas de caractères de nouvelles lignes , les meilleures performances seront atteintes avec l ' option PCRE_DOTALL , ou en ancrant le masque avec ^.* . Cela évite à PCRE de scanner toute la chaîne pour rechercher un caractère de nouvelle ligne et recommencer la recherche .

Attention aux masques qui contiennent des quantificateurs infinis imbriqués . Ils peuvent demander un temps de calcul très long , lorsqu ' appliqués à une chaîne qui ne correspond pas à ce masque . Par exemple , ( a+)* peut accepter " aaaa " de 33 manières différentes , et ce nombre croit rapidement avec la taille de la chaîne (le quantificateur * peut prendre les valeurs de 0 , 1 , 2 , 3 , ou 4 , et pour chaque cas non nul , le quantificateur + peut prendre différentes valeurs ) .

Lorsque le reste de la chaîne est tel que l' on s 'achemine vers un échec , PCRE doit en principe vérifier toutes les possibilités , et cela prend un temps extrêmement long . Un optmiseur repère les cas les plus simples , tel que ( a+ )*b un caractère simple suit les quantificateurs . Avant de partir dans les procédures standard de recherche , PCRE s' assure qu'il y a au moins un " b " dans la chaîne , et si ce n'est pas le cas , l 'échec est annoncé immédiatement . Sinon , il n' y a pas d 'optimisation dans la recherche . Vous pouvez voir la différence de comportement avec le masque suivant : ( a+ )*\d . Le premier retourne un échec quasi-immédiatement , s' il est appliqué à une ligne de " a " , alors que le second masque prend un temps significatif pour une chaîne de plus de 20 caractères .