Files
doc-fr/reference/pcre/pattern.syntax.xml
Pierrick Charron c2bbb831b4 Sync reference/pcre
2023-08-24 09:09:27 -04:00

2630 lines
100 KiB
XML
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 587830d5d261802148a160a59059dd8d76385fd2 Maintainer: yannick Status: ready -->
<!-- Reviewed: no -->
<chapter xml:id="reference.pcre.pattern.syntax" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Syntaxe des masques</title>
<titleabbrev>Fonctionnement des expressions régulières</titleabbrev>
<section xml:id="regexp.introduction">
&reftitle.intro;
<para>
La syntaxe et la sémantique des expressions régulières
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.
Le livre de Jeffrey Friedl "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.
</para>
<para>
Une expression rationnelle 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 "<literal>Le rapide renard gris</literal>",
pourra correspondre à une partie de la chaîne sujet qui sera
identique au masque, par exemple
"<literal>Le rapide renard gris court dans la forêt</literal>",
</para>
</section>
<section xml:id="regexp.reference.delimiters">
<title>Délimiteurs</title>
<para>
Lors de l'utilisation des fonctions PCRE, il est nécessaire que le motif soit encadré
par des <emphasis>délimiteurs</emphasis>. Un délimiteur peut être n'importe quel caractère
non alpha-numérique autre qu'un backslash ou qu'un espace.
Les caractères d'espacement blanc avant un délimiteur valide sont silencieusement ignoré.
</para>
<para>
Les délimiteurs les plus courants sont les slashes (<literal>/</literal>), dièses
(<literal>#</literal>) et les tildes (<literal>~</literal>). Les exemples suivants ont
tous des motifs encadrés avec des délimiteurs valides.
<informalexample>
<programlisting>
<![CDATA[
/foo bar/
#^[^0-9]$#
+php+
%[a-zA-Z0-9_-]%
]]>
</programlisting>
</informalexample>
</para>
<para>
Il est également possible d'utiliser les délimiteurs utilisant les crochets
où les crochets ouvrants et fermants sont respectivement les délimiteurs de
début et de fin. <literal>()</literal>, <literal>{}</literal>,
<literal>[]</literal> and <literal>&lt;&gt;</literal> sont tous des styles
de crochets valides.
<informalexample>
<programlisting>
<![CDATA[
(this [is] a (pattern))
{this [is] a (pattern)}
[this [is] a (pattern)]
<this [is] a (pattern)>
]]>
</programlisting>
</informalexample>
Les délimiteurs utilisant les crochets n'ont pas besoin d'être échappés lorsqu'ils
sont utilisés comme caractères méta dans un masque, mais, comme tout autre opérateur,
ils doivent être échappés s'ils sont utilisés comme caractères littéraux.
</para>
<para>
Si le délimiteur doit être décrit dans le motif, il doit être échappé avec un backslash.
Si le délimiteur apparait souvent dans le motif, choisir un autre délimiteur est une bonne
idée pour en augmenter la lisibilité.
<informalexample>
<programlisting>
<![CDATA[
/http:\/\//
#http://#
]]>
</programlisting>
</informalexample>
La fonction <function>preg_quote</function> peut être utilisée pour échapper une chaine
et l'utiliser dans un motif. Son second paramètre optionnel sert à spécifier le délimiteur
qui doit être échappé.
</para>
<para>
Vous pouvez aussi utiliser des <link linkend="reference.pcre.pattern.modifiers">
modificateurs de motif</link> après le délimiteur final. L'exemple suivant montre
une correspondance insensible à la casse.
<informalexample>
<programlisting>
<![CDATA[
#[a-z]#i
]]>
</programlisting>
</informalexample>
</para>
</section>
<section xml:id="regexp.reference.meta">
<title>Métacaractères</title>
<para>
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 <emphasis>métacaractères</emphasis>, qui ne représentent
pas ce qu'ils sont, mais sont interprétés d'une certaine
manière.
</para>
<para>
Il y a deux sortes de métacaractères : ceux qui sont
reconnus n'importe où dans un masque, hormis entre crochets,
et ceux qui sont reconnus entre crochets.
À l'extérieur des crochets, les métacaractères sont :
<table>
<title>Métacaractère en dehors des crochets</title>
<tgroup cols="2">
<thead>
<row>
<entry>Métacaractère</entry><entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>\</entry><entry>Caractère d'échappement, avec de multiples usages</entry>
</row>
<row>
<entry>^</entry><entry>Le début de la chaîne sujet (ou de ligne, en mode multilignes)</entry>
</row>
<row>
<entry>$</entry><entry>La fin de la chaîne sujet ou avant la fin d'une nouvelle ligne (ou fin de ligne, en mode multilignes)</entry>
</row>
<row>
<entry>.</entry><entry>Remplace n'importe quel caractère, hormis le caractère de nouvelle ligne (par défaut)</entry>
</row>
<row>
<entry>[</entry><entry>Caractère de début de définition de classe</entry>
</row>
<row>
<entry>]</entry><entry>Caractère de fin de définition de classe</entry>
</row>
<row>
<entry>|</entry><entry>Caractère de début d'alternative</entry>
</row>
<row>
<entry>(</entry><entry>Caractère de début de sous-masque</entry>
</row>
<row>
<entry>)</entry><entry>Caractère de fin de sous-masque</entry>
</row>
<row>
<entry>?</entry><entry>Étend le sens de (; quantificateur de 0 ou 1; quantificateur de minimisation
(Voir les <link linkend="regexp.reference.repetition">répétitions</link>)</entry>
</row>
<row>
<entry>*</entry><entry>Quantificateur de 0 ou plus</entry>
</row>
<row>
<entry>+</entry><entry>Quantificateur de 1 ou plus</entry>
</row>
<row>
<entry>{</entry><entry>Caractère de début de quantificateur minimum/maximum</entry>
</row>
<row>
<entry>}</entry><entry>Caractère de fin de quantificateur minimum/maximum</entry>
</row>
</tbody>
</tgroup>
</table>
La partie du masque qui est entourée de crochets est appelée
classe de caractères. Dans
<link linkend="regexp.reference.character-classes">les classes de caractères</link>,
les seuls métacaractères autorisés sont :
<table>
<title>Meta-characters dans des crochets (<emphasis>classes de caractères</emphasis>)</title>
<tgroup cols="2">
<thead>
<row>
<entry>Métacaractère</entry><entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>\</entry><entry>Caractère de protection, avec de multiples usages</entry>
</row>
<row>
<entry>^</entry><entry>Négation de la classe, mais uniquement si placé tout au début de la classe</entry>
</row>
<row>
<entry>-</entry><entry>Indique un intervalle de caractères</entry>
</row>
</tbody>
</tgroup>
</table>
La section suivante décrit l'utilisation de chaque
métacaractère.
</para>
</section>
<section xml:id="regexp.reference.escape">
<title>Séquences d'échappement</title>
<para>
Le caractère antislash a de nombreuses utilisations.
En premier lieu, s'il est suivi d'un caractère non
alphanumérique, il ne prendra pas la signification
spéciale qui y est rattachée. Cette utilisation de
l'antislash comme caractère de protection s'applique
à l'intérieur et à l'extérieur des
classes de caractères.
</para>
<para>
Par exemple, pour rechercher le
caractère étoile "<literal>*</literal>", il faut
écrire dans le masque : "<literal>\*</literal>". Cela
s'applique dans tous les cas, que le caractère qui suive
soit un métacaractè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 antislashs,
il faut écrire : "<literal>\\</literal>".
</para>
<note>
<para>
La <link linkend="language.types.string.syntax">chaîne de caractères</link> PHP
simple ou double guillemet a une signification spéciale des antislashs. Donc,
si \ doit être recherché avec une expression rationnelle \\, alors
"\\\\" ou '\\\\' doit être utilisé dans le code PHP.
</para>
</note>
<para>
Si un masque est utilisé avec l'option
<link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link>,
les espaces blancs du masque, mais qui ne sont pas dans une
classe de caractères et les caractères entre dièse
"<literal>#</literal>", ainsi que les nouvelles lignes sont ignorées.
L'antislash peut être utilisé pour les protéger et ainsi
rechercher un espace ou un dièse.
</para>
<para>
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'elles représentent :
</para>
<para>
<variablelist>
<varlistentry>
<term><emphasis>\a</emphasis></term>
<listitem>
<simpara>
alarme, c'est-à-dire le caractère BEL (hex 07)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\cx</emphasis></term>
<listitem>
<simpara>
"contrôle-x", avec x qui peut être n'importe quel
caractère.
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\e</emphasis></term>
<listitem>
<simpara>
escape (hex 1B)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\f</emphasis></term>
<listitem>
<simpara>
formfeed (hex 0C)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\n</emphasis></term>
<listitem>
<simpara>
nouvelle ligne (hex 0A)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\p{xx}</emphasis></term>
<listitem>
<simpara>
un caractère avec une propriété xx, voir
les <link linkend="regexp.reference.unicode">propriétés unicode</link>
pour plus d'informations
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\P{xx}</emphasis></term>
<listitem>
<simpara>
un caractère sans propriété xx, voir
les <link linkend="regexp.reference.unicode">propriétés unicode</link>
pour plus d'informations
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\r</emphasis></term>
<listitem>
<simpara>
retour chariot (hex 0D)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\R</emphasis></term>
<listitem>
<simpara>saut de ligne : satisfait par \n, \r et \r\n</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\t</emphasis></term>
<listitem>
<simpara>
tabulation (hex 09)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\xhh</emphasis></term>
<listitem>
<simpara>
caractère en hexadécimal, de code hh
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\ddd</emphasis></term>
<listitem>
<simpara>
caractère en octal, de code ddd, ou référence
arrière
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Dans la séquence "<literal>\cx</literal>" si "<literal>x</literal>"
est en minuscule, il est converti en majuscule. Puis, le bit 6 (hex 40)
est inversé. Ainsi "<literal>\cz</literal>" devient <literal>1A</literal>,
mais "<literal>\c{</literal>" devient hex 3B, tandis que "<literal>\c;</literal>"
devient hex 7B.
</para>
<para>
Après "<literal>\x</literal>", deux caractères
hexadécimaux sont lus (les lettres peuvent être en majuscule
ou minuscule).
En mode <emphasis>UTF-8</emphasis>, "<literal>\x{...}</literal>"
est autorisée, où le contenu des accolades est une chaîne hexadécimale.
Il sera interprété comme un caractère UTF-8 où le numéro de code est
le numéro hexadécimal donné. La séquence d'échappement hexadécimale
originale, <literal>\xhh</literal>, correspond à un caractère UTF-8
sur 2 octets si la valeur est plus grande que 127.
</para>
<para>
Après "<literal>\0</literal>", deux caractères octaux sont lus.
Dans chacun des cas, le métacaractère tente de lire autant
de caractères que possible. Ainsi, la séquence
"<literal>\0\x\07</literal>" sera comprise comme deux caractères nuls,
suivis d'un caractère alarme (BEL). Assurez-vous que vous fournissez
suffisamment de chiffres après le métacaractère.
</para>
<para>
L'antislash de fin suivi par un nombre autre que 0 est compliqué.
À l'extérieur d'une classe de caractère, PCRE le lit, et tous les nombres
qui suivent, en tant que nombres décimaux. Si le nombre est plus petit que
10 ou s'il y a eu au moins précédemment une parenthèse gauche capturante
dans l'expression, la séquence entière est prise en tant que <emphasis>référence arrière</emphasis>.
Une description sur le fonctionnement est donnée plus tard, suivez la discussion
sur les parenthèses des sous masques.
</para>
<para>
À l'intérieur d'un caractère de classe ou s'il est plus
grand que 9, et qu'il n'y a pas eu assez de parenthèses ouvrantes
auparavant, PCRE lit jusqu'à 3 chiffres octaux à 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 représentent
eux-mêmes. Par exemple:
</para>
<para>
<variablelist>
<varlistentry>
<term><emphasis>\040</emphasis></term>
<listitem>
<simpara>
une autre manière d'écrire un espace
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\40</emphasis></term>
<listitem>
<simpara>
identique, dans la mesure où il n'y a pas 40
parenthèses ouvrantes auparavant
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\7</emphasis></term>
<listitem>
<simpara>
est toujours une référence arrière
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\11</emphasis></term>
<listitem>
<simpara>
peut être une référence de retour,
ou une tabulation
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\011</emphasis></term>
<listitem>
<simpara>
toujours une tabulation
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\0113</emphasis></term>
<listitem>
<simpara>
est une tabulation suivie du caractère "3"
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\113</emphasis></term>
<listitem>
<simpara>
est le caractère 113 (étant donné qu'il ne
peut y avoir plus de 99 références arrière)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\377</emphasis></term>
<listitem>
<simpara>
est un octet dont tous les bits sont à 1
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\81</emphasis></term>
<listitem>
<simpara>
peut être soit une référence arrière,
soit un zéro binaire suivi des caractères "8" et "1"
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Les valeurs octales supérieures ou égales à 100 ne
doivent pas être introduites par un 0, car seuls les trois premiers
octets seront lus.
</para>
<para>
Toutes les séquences qui définissent une valeur d'un seul
octet peuvent être utilisées dans les classes de caractères,
et à l'extérieur. De plus, dans une classe de caractères,
la séquence "<literal>\b</literal>" est interprétée
comme un caractère effacer (hex 08). À l'extérieur,
elle peut avoir d'autres significations
(voir ci-dessous).
</para>
<para>
On peut encore se servir de l'antislash pour préciser des types
génériques de valeurs :
</para>
<para>
<variablelist>
<varlistentry>
<term><emphasis>\d</emphasis></term>
<listitem>
<simpara>
tout caractère décimal
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\D</emphasis></term>
<listitem>
<simpara>
tout caractère qui n'est pas un caractère décimal
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\h</emphasis></term>
<listitem>
<simpara>
n'importe quel espace horizontal
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\H</emphasis></term>
<listitem>
<simpara>
n'importe quel caractère qui n'est pas un espace horizontal
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\s</emphasis></term>
<listitem>
<simpara>
tout caractère blanc
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\S</emphasis></term>
<listitem>
<simpara>
tout caractère qui n'est pas un caractère blanc
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\v</emphasis></term>
<listitem>
<simpara>
n'importe quel espace vertical
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\V</emphasis></term>
<listitem>
<simpara>
n'importe quel caractère qui n'est pas un espace vertical
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\w</emphasis></term>
<listitem>
<simpara>
tout caractère de "mot"
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\W</emphasis></term>
<listitem>
<simpara>
tout caractère qui n'est pas un caractère de "mot"
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
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étacaractère,
soit l'autre.
</para>
<para>
Les caractères "blancs" sont HT (9), LF (10), FF (12), CR (13),
et espace (32). Cependant, lors de l'utilisation d'une locale
particulière, tous les caractères se trouvant dans l'intervalle
128-255 peuvent aussi être considérés comme caractère blanc, par exemple
NBSP (A0).
</para>
<para>
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 <emphasis>mot</emphasis> 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ères. 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étacaractère <literal>\w</literal>.
</para>
<para>
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.
</para>
<para>
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écrite
plus bas. Les assertions avec antislash sont les suivantes :
</para>
<para>
<variablelist>
<varlistentry>
<term><emphasis>\b</emphasis></term>
<listitem>
<simpara>
limite de mot
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\B</emphasis></term>
<listitem>
<simpara>
pas limite de mot
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\A</emphasis></term>
<listitem>
<simpara>
début de la chaîne sujet
(indépendant du mode multilignes)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\Z</emphasis></term>
<listitem>
<simpara>
fin de la chaîne sujet ou nouvelle ligne à
la fin de la chaîne sujet
(indépendant du mode multilignes)
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\G</emphasis></term>
<listitem>
<simpara>
position de la première occurrence trouvée dans la chaîne sujet
</simpara>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\z</emphasis></term>
<listitem>
<simpara>
fin de la chaîne sujet
(indépendant du mode multilignes)
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Ces assertions ne peuvent pas apparaître dans une classe de
caractères (mais "<literal>\b</literal>" a une autre signification à
l'intérieur d'une classe de caractères).
</para>
<para>
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 (<literal>\w</literal>), ou le contraire (<literal>\W</literal>)
(on peut le voir comme <literal>\w\W</literal> ou <literal>\W\w</literal>), ou encore le
premier ou le dernier caractère est un caractère mot (<literal>\w</literal>).
</para>
<para>
Les assertions <literal>\A</literal>, <literal>\Z</literal>, et
<literal>\z</literal> diffèrent des métacaractères
<literal>^</literal> et <literal>$</literal>
(décrit dans <link linkend="regexp.reference.anchors">les ancres</link>)
dans la mesure où ils ne sont pas dépendants des options, notamment
<link linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link>
ou <link linkend="reference.pcre.pattern.modifiers">PCRE_DOLLAR_ENDONLY</link>.
La différence entre <literal>\Z</literal> et
<literal>\z</literal> tient au fait que <literal>\Z</literal> recherche
les positions avant les nouvelles lignes et à la fin de la
chaîne sujet, tandis que <literal>\z</literal> ne recherche
que la fin de la chaîne.
</para>
<para>
L'assertion <literal>\G</literal> est réalisée uniquement lorsque
la position courante de l'occurrence trouvée est au début de l'occurrence,
comme spécifié par l'argument <parameter>offset</parameter> de la
fonction <function>preg_match</function>. Elle diffère de <literal>\A</literal>
lorsque la valeur du paramètre <parameter>offset</parameter> est différente
de zéro.
</para>
<para>
<literal>\Q</literal> et <literal>\E</literal> peuvent être utilisés
pour ignorer les métacaractères dans le masque.
Par exemple : <literal>\w+\Q.$.\E$</literal> recherchera un ou plusieurs
caractères suivis par la chaîne littérale <literal>.$.</literal> et ancrés à la
fin de la chaîne.
Il est à noter que ceci ne change pas le comportement des délimiteurs;
par exemple le masque <literal>#\Q#\E#$</literal> n'est pas valide, car
le second <literal>#</literal> marque la fin du masque, et que
<literal>\E#</literal> est interprété comme un modificateur invalide.
</para>
<para>
<literal>\K</literal> peut être utilisé pour réinitialiser le résultat
Par exemple, le masque <literal>foo\Kbar</literal> trouve
"foobar", mais reporte qu'il a trouvé "bar". L'utilisation de
<literal>\K</literal> n'interfère pas avec la configuration des sous-chaînes capturantes.
Par exemple, lorsque le masque <literal>(foo)\Kbar</literal>
trouve "foobar", la première sous-chaîne sera toujours "foo".
</para>
</section>
<section xml:id="regexp.reference.unicode">
<title>Propriétés des caractères Unicode</title>
<para>
Trois nouvelles séquences d'échappement
pour trouver des types de caractères sont disponibles lorsque
le mode <emphasis>UTF-8</emphasis> est sélectionné. Elles sont :
</para>
<variablelist>
<varlistentry>
<term><emphasis>\p{xx}</emphasis></term>
<listitem><simpara>un caractère avec les propriétés xx</simpara></listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\P{xx}</emphasis></term>
<listitem><simpara>un caractère sans les propriétés xx</simpara></listitem>
</varlistentry>
<varlistentry>
<term><emphasis>\X</emphasis></term>
<listitem><simpara>une séquence étendue Unicode</simpara></listitem>
</varlistentry>
</variablelist>
<para>
Les noms des propriétés représentés par <literal>xx</literal> ci-dessus
sont limités aux catégories de propriétés générales Unicode. Chaque caractère
a exactement une seule de ces propriétés, spécifié par une abréviation sur deux caractères.
Pour des raisons de compatibilité avec Perl, la négation peut être spécifiée
en incluant un accent circonflexe entre l'accolade ouvrante et le nom de la
propriété. Par exemple, <literal>\p{^Lu}</literal> équivaut à la même chose que
<literal>\P{Lu}</literal>.
</para>
<para>
Si une seule lettre est spécifiée avec <literal>\p</literal> ou <literal>\P</literal>,
il inclut toutes les propriétés qui commencent par cette lettre. Dans ce cas,
en l'absence de négation, les accolades dans la séquence d'échappement sont
optionnelles ; ceci revient à la même chose :
</para>
<informalexample>
<programlisting>
<![CDATA[
\p{L}
\pL
]]>
</programlisting>
</informalexample>
<table>
<title>Codes des propriétés supportées</title>
<tgroup cols="3">
<thead>
<row>
<entry>Propriétés</entry>
<entry>Correspondance</entry>
<entry>Notes</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>C</literal></entry>
<entry>Autre</entry>
<entry></entry>
</row>
<row>
<entry><literal>Cc</literal></entry>
<entry>Contrôle</entry>
<entry></entry>
</row>
<row>
<entry><literal>Cf</literal></entry>
<entry>Format</entry>
<entry></entry>
</row>
<row>
<entry><literal>Cn</literal></entry>
<entry>Non affecté</entry>
<entry></entry>
</row>
<row>
<entry><literal>Co</literal></entry>
<entry>Utilisation privée</entry>
<entry></entry>
</row>
<row rowsep="1">
<entry><literal>Cs</literal></entry>
<entry>Substitut</entry>
<entry></entry>
</row>
<row>
<entry><literal>L</literal></entry>
<entry>Lettre</entry>
<entry>
Inclut les propriétés suivantes : <literal>Ll</literal>,
<literal>Lm</literal>, <literal>Lo</literal>, <literal>Lt</literal> et
<literal>Lu</literal>.
</entry>
</row>
<row>
<entry><literal>Ll</literal></entry>
<entry>Lettre en minuscule</entry>
<entry></entry>
</row>
<row>
<entry><literal>Lm</literal></entry>
<entry>Lettre de modification</entry>
<entry></entry>
</row>
<row>
<entry><literal>Lo</literal></entry>
<entry>Autres lettres</entry>
<entry></entry>
</row>
<row>
<entry><literal>Lt</literal></entry>
<entry>Lettre titrée</entry>
<entry></entry>
</row>
<row rowsep="1">
<entry><literal>Lu</literal></entry>
<entry>Lettre en majuscule</entry>
<entry></entry>
</row>
<row>
<entry><literal>M</literal></entry>
<entry>Marque</entry>
<entry></entry>
</row>
<row>
<entry><literal>Mc</literal></entry>
<entry>Marque d'espacement</entry>
<entry></entry>
</row>
<row>
<entry><literal>Me</literal></entry>
<entry>Marque d'enfermement</entry>
<entry></entry>
</row>
<row rowsep="1">
<entry><literal>Mn</literal></entry>
<entry>Marque non espacée</entry>
<entry></entry>
</row>
<row>
<entry><literal>N</literal></entry>
<entry>Nombre</entry>
<entry></entry>
</row>
<row>
<entry><literal>Nd</literal></entry>
<entry>Nombre décimal</entry>
<entry></entry>
</row>
<row>
<entry><literal>Nl</literal></entry>
<entry>Nombre Lettre</entry>
<entry></entry>
</row>
<row rowsep="1">
<entry><literal>No</literal></entry>
<entry>Autres nombres</entry>
<entry></entry>
</row>
<row>
<entry><literal>P</literal></entry>
<entry>Ponctuation</entry>
<entry></entry>
</row>
<row>
<entry><literal>Pc</literal></entry>
<entry>Ponctuation de connecteur</entry>
<entry></entry>
</row>
<row>
<entry><literal>Pd</literal></entry>
<entry>Tiret de ponctuation</entry>
<entry></entry>
</row>
<row>
<entry><literal>Pe</literal></entry>
<entry>Ponctuation de fermeture</entry>
<entry></entry>
</row>
<row>
<entry><literal>Pf</literal></entry>
<entry>Ponctuation finale</entry>
<entry></entry>
</row>
<row>
<entry><literal>Pi</literal></entry>
<entry>Ponctuation initiale</entry>
<entry></entry>
</row>
<row>
<entry><literal>Po</literal></entry>
<entry>Autres ponctuations</entry>
<entry></entry>
</row>
<row rowsep="1">
<entry><literal>Ps</literal></entry>
<entry>Ponctuation ouvrante</entry>
<entry></entry>
</row>
<row>
<entry><literal>S</literal></entry>
<entry>Symbole</entry>
<entry></entry>
</row>
<row>
<entry><literal>Sc</literal></entry>
<entry>Symbole monétaire</entry>
<entry></entry>
</row>
<row>
<entry><literal>Sk</literal></entry>
<entry>Symbole de modification</entry>
<entry></entry>
</row>
<row>
<entry><literal>Sm</literal></entry>
<entry>Symbole mathématique</entry>
<entry></entry>
</row>
<row rowsep="1">
<entry><literal>So</literal></entry>
<entry>Autres symboles</entry>
<entry></entry>
</row>
<row>
<entry><literal>Z</literal></entry>
<entry>Séparateur</entry>
<entry></entry>
</row>
<row>
<entry><literal>Zl</literal></entry>
<entry>Séparateur de ligne</entry>
<entry></entry>
</row>
<row>
<entry><literal>Zp</literal></entry>
<entry>Séparateur de paragraphe</entry>
<entry></entry>
</row>
<row>
<entry><literal>Zs</literal></entry>
<entry>Séparateur d'espace</entry>
<entry></entry>
</row>
</tbody>
</tgroup>
</table>
<para>
Les propriétés étendues comme <literal>InMusicalSymbols</literal> ne sont pas supportées
par PCRE.
</para>
<para>
La sensibilité à la casse de la recherche n'affecte pas les
séquences d'échappement. Par exemple, <literal>\p{Lu}</literal>
cherche toujours et uniquement les lettres en majuscules
</para>
<para>
Les jeux de caractères unicodes sont définis comme appartenant à certains scripts.
Un caractère d'un de ces jeux peut être trouvé en utilisant un
nom de script. Par exemple :
</para>
<itemizedlist>
<listitem>
<simpara><literal>\p{Greek}</literal></simpara>
</listitem>
<listitem>
<simpara><literal>\P{Han}</literal></simpara>
</listitem>
</itemizedlist>
<para>
Ceux qui ne font pas partis d'un script identifié sont regroupés
dans <literal>Common</literal>. Voici la liste courante des scripts :
</para>
<table>
<title>Scripts supportés</title>
<tgroup cols="5">
<tbody>
<row>
<entry><literal>Arabic</literal></entry>
<entry><literal>Armenian</literal></entry>
<entry><literal>Avestan</literal></entry>
<entry><literal>Balinese</literal></entry>
<entry><literal>Bamum</literal></entry>
</row>
<row>
<entry><literal>Batak</literal></entry>
<entry><literal>Bengali</literal></entry>
<entry><literal>Bopomofo</literal></entry>
<entry><literal>Brahmi</literal></entry>
<entry><literal>Braille</literal></entry>
</row>
<row>
<entry><literal>Buginese</literal></entry>
<entry><literal>Buhid</literal></entry>
<entry><literal>Canadian_Aboriginal</literal></entry>
<entry><literal>Carian</literal></entry>
<entry><literal>Chakma</literal></entry>
</row>
<row>
<entry><literal>Cham</literal></entry>
<entry><literal>Cherokee</literal></entry>
<entry><literal>Common</literal></entry>
<entry><literal>Coptic</literal></entry>
<entry><literal>Cuneiform</literal></entry>
</row>
<row>
<entry><literal>Cypriot</literal></entry>
<entry><literal>Cyrillic</literal></entry>
<entry><literal>Deseret</literal></entry>
<entry><literal>Devanagari</literal></entry>
<entry><literal>Egyptian_Hieroglyphs</literal></entry>
</row>
<row>
<entry><literal>Ethiopic</literal></entry>
<entry><literal>Georgian</literal></entry>
<entry><literal>Glagolitic</literal></entry>
<entry><literal>Gothic</literal></entry>
<entry><literal>Greek</literal></entry>
</row>
<row>
<entry><literal>Gujarati</literal></entry>
<entry><literal>Gurmukhi</literal></entry>
<entry><literal>Han</literal></entry>
<entry><literal>Hangul</literal></entry>
<entry><literal>Hanunoo</literal></entry>
</row>
<row>
<entry><literal>Hebrew</literal></entry>
<entry><literal>Hiragana</literal></entry>
<entry><literal>Imperial_Aramaic</literal></entry>
<entry><literal>Inherited</literal></entry>
<entry><literal>Inscriptional_Pahlavi</literal></entry>
</row>
<row>
<entry><literal>Inscriptional_Parthian</literal></entry>
<entry><literal>Javanese</literal></entry>
<entry><literal>Kaithi</literal></entry>
<entry><literal>Kannada</literal></entry>
<entry><literal>Katakana</literal></entry>
</row>
<row>
<entry><literal>Kayah_Li</literal></entry>
<entry><literal>Kharoshthi</literal></entry>
<entry><literal>Khmer</literal></entry>
<entry><literal>Lao</literal></entry>
<entry><literal>Latin</literal></entry>
</row>
<row>
<entry><literal>Lepcha</literal></entry>
<entry><literal>Limbu</literal></entry>
<entry><literal>Linear_B</literal></entry>
<entry><literal>Lisu</literal></entry>
<entry><literal>Lycian</literal></entry>
</row>
<row>
<entry><literal>Lydian</literal></entry>
<entry><literal>Malayalam</literal></entry>
<entry><literal>Mandaic</literal></entry>
<entry><literal>Meetei_Mayek</literal></entry>
<entry><literal>Meroitic_Cursive</literal></entry>
</row>
<row>
<entry><literal>Meroitic_Hieroglyphs</literal></entry>
<entry><literal>Miao</literal></entry>
<entry><literal>Mongolian</literal></entry>
<entry><literal>Myanmar</literal></entry>
<entry><literal>New_Tai_Lue</literal></entry>
</row>
<row>
<entry><literal>Nko</literal></entry>
<entry><literal>Ogham</literal></entry>
<entry><literal>Old_Italic</literal></entry>
<entry><literal>Old_Persian</literal></entry>
<entry><literal>Old_South_Arabian</literal></entry>
</row>
<row>
<entry><literal>Old_Turkic</literal></entry>
<entry><literal>Ol_Chiki</literal></entry>
<entry><literal>Oriya</literal></entry>
<entry><literal>Osmanya</literal></entry>
<entry><literal>Phags_Pa</literal></entry>
</row>
<row>
<entry><literal>Phoenician</literal></entry>
<entry><literal>Rejang</literal></entry>
<entry><literal>Runic</literal></entry>
<entry><literal>Samaritan</literal></entry>
<entry><literal>Saurashtra</literal></entry>
</row>
<row>
<entry><literal>Sharada</literal></entry>
<entry><literal>Shavian</literal></entry>
<entry><literal>Sinhala</literal></entry>
<entry><literal>Sora_Sompeng</literal></entry>
<entry><literal>Sundanese</literal></entry>
</row>
<row>
<entry><literal>Syloti_Nagri</literal></entry>
<entry><literal>Syriac</literal></entry>
<entry><literal>Tagalog</literal></entry>
<entry><literal>Tagbanwa</literal></entry>
<entry><literal>Tai_Le</literal></entry>
</row>
<row>
<entry><literal>Tai_Tham</literal></entry>
<entry><literal>Tai_Viet</literal></entry>
<entry><literal>Takri</literal></entry>
<entry><literal>Tamil</literal></entry>
<entry><literal>Telugu</literal></entry>
</row>
<row>
<entry><literal>Thaana</literal></entry>
<entry><literal>Thai</literal></entry>
<entry><literal>Tibetan</literal></entry>
<entry><literal>Tifinagh</literal></entry>
<entry><literal>Ugaritic</literal></entry>
</row>
<row>
<entry><literal>Vai</literal></entry>
<entry><literal>Yi</literal></entry>
<entry />
<entry />
<entry />
<entry />
</row>
</tbody>
</tgroup>
</table>
<para>
La séquence <literal>\X</literal> cherche n'importe quel groupe de
graphème Unicode étendu. Un groupe de graphème est une chaîne
composée d'un ou plusieurs caractères Unicode qui se combinent
pour former un seul glyphe. Dans les faits, cela revient à utiliser
le caractère <literal>.</literal> sachant qu'il va matcher un
caractère composé, peu importe le nombre de caractères individuel
nécessaire à l'afficher.
</para>
<para>
Dans les versions PCRE inférieures à 8.32 (ce qui correspond aux
versions de PHP antérieures à la version 5.4.14 lorsque la
bibliothèque interne est utilisée), <literal>\X</literal> était
équivalent à <literal>(?>\PM\pM*)</literal>. Aussi, il matchait
un caractère sans propriété "mark", suivi par aucun ou plusieurs
caractères possédant la propriété "mark", et traitait la séquence
comme un groupe atomique (voir ci-dessous). Les caractères
avec la propriété "mark" sont typiquement les lettres accentuées
qui affectent le caractère qui la précède.
</para>
<para>
La recherche de caractères par les propriétés Unicode n'est pas la méthode
la plus rapide, car PCRE doit chercher une structure qui contient les données
dans plus de quinze mille caractères. C'est pour cela que les séquences
traditionnelles comme <literal>\d</literal> et
<literal>\w</literal> n'utilisent pas les propriétés Unicode dans PCRE.
</para>
</section>
<section xml:id="regexp.reference.anchors">
<title>Ancres</title>
<para>
En dehors d'une classe de caractères, avec les options par
défaut, <literal>^</literal> est une assertion qui n'est
vraie que si elle est placée tout au début de la
chaîne. À l'intérieur d'une classe de caractères,
<literal>^</literal> a un tout autre sens (voir ci-dessous).
</para>
<para>
<literal>^</literal> 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 <literal>^</literal>, alors le masque est dit ancré
(il y a une autre construction qui porte cette appellation).
</para>
<para>
<literal>$</literal> 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. À l'intérieur d'une
classe de caractères, <literal>$</literal> a un tout autre
sens (voir ci-dessous).
<literal>$</literal> 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
<literal>$</literal>, alors le masque est dit ancré (il y
a une autre construction qui porte cette appellation). <literal>$</literal>
n'a pas de valeur particulière dans une classe de
caractères.
</para>
<para>
La signification de <literal>$</literal> 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
<link linkend="reference.pcre.pattern.modifiers">PCRE_DOLLAR_ENDONLY</link>
au moment de la compilation, ou de l'exécution.
Cette option est inopérante sur <literal>\Z</literal>.
</para>
<para>
La signification de <literal>^</literal> 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 "<literal>\n</literal>". Cela se fait en ajoutant l'option
<link linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link> au moment de
la compilation ou de l'exécution.
Par exemple, le masque <literal>/^abc$/</literal> accepte la chaîne
"<literal>def\nabc</literal>" uniquement en mode multilignes. Par
conséquent, toutes les parties du masque qui commencent par
"<literal>^</literal>" ne sont pas ancrées, en mode multilignes.
L'option <link linkend="reference.pcre.pattern.modifiers">PCRE_DOLLAR_ENDONLY</link>
est ignorée si l'option
<link linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link> est choisie.
</para>
<para>
Notez que les métacaractères <literal>\A</literal>,
<literal>\Z</literal>, et <literal>\z</literal> peuvent servir à
repérer le début et la fin du sujet, et toutes les
parties du masque qui commenceront par <literal>\A</literal> seront toujours
ancrées, avec l'option
<link linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link> ou non.
</para>
</section>
<section xml:id="regexp.reference.dot">
<title>Point</title>
<para>
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
<link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link> 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 <literal>^</literal> et <literal>$</literal>.
Le seul point commun est que les deux ont un comportement particulier vis-à-vis
des caractères de nouvelle ligne.
Le point n'a pas de comportement particulier dans une classe de
caractères.
</para>
<para>
<emphasis>\C</emphasis> peut être utilisé pour chercher un seul octet.
Il prend tout son sens en mode <emphasis>UTF-8</emphasis>
où le point correspond à un caractère entier qui peut être constitué de plusieurs
octets.
</para>
</section>
<section xml:id="regexp.reference.character-classes">
<title>Classes de caractères</title>
<para>
Un crochet ouvrant <literal>[</literal> introduit une classe de
caractères, et le crochet fermant <literal>]</literal>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 <literal>^</literal> éventuel)
ou protégé avec un antislash.
</para>
<para>
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
<literal>^</literal>, qui représente une négation :
le caractère ne doit pas se trouver dans la classe. Si
<literal>^</literal> est nécessaire dans la classe, il
suffit qu'il ne soit pas le premier caractère, ou bien
qu'il soit protégé par un antislash.
</para>
<para>
Par exemple, le caractère <literal>[aeiou]</literal> remplace
n'importe quelle voyelle minuscule, tandis que <literal>[^aeiou]</literal>
remplace n'importe quel caractère qui n'est pas une voyelle
minuscule. <literal>^</literal> 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é.
</para>
<para>
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, <literal>[aeiou]</literal>
représentera "<literal>A</literal>" ou "<literal>a</literal>", et
<literal>[^aeiou]</literal> n'acceptera pas "<literal>A</literal>",
tandis que sans l'option, elle l'accepterait.
</para>
<para>
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 <link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link>
ou <link linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link>. Une classe
telle que <literal>[^a]</literal> acceptera toujours une nouvelle ligne.
</para>
<para>
Le signe moins (<literal>-</literal>) est utilisé pour
spécifier un intervalle de caractères, dans
une classe. Par exemple, <literal>[d-m]</literal> remplace toutes
les lettres entre d et m inclus. Si le caractère moins est
requis dans une classe, il faut le protéger avec un antislash,
ou le faire apparaître à une position où il ne pourra
pas être interprété comme une indication d'intervalle,
c'est-à-dire au début ou à la fin de la classe.
</para>
<para>
Il n'est pas possible d'avoir le caractère crochet fermant
"<literal>]</literal>" comme fin d'intervalle. Un masque tel que
<literal>[W-]46]</literal> est compris comme la classe de caractères
contenant deux caractères ("W" et "-") suivie de la chaîne
littérale "46]", ce qui fait qu'il va accepter
"<literal>W46]</literal>" ou "<literal>-46]</literal>". Cependant, si
"<literal>]</literal>" est protégé avec un antislash, le
masque <literal>[W-\]46]</literal> est interprété comme
une classe d'un seul caractère, contenant un intervalle de
caractères. La valeur octale ou hexadécimale de
"<literal>]</literal>" peut aussi être utilisée pour déterminer
les limites de l'intervalle.
</para>
<para>
Les intervalles travaillent sur des séquences ASCII.
Ils peuvent aussi être précisés avec des valeurs numériques :
par exemple "<literal>[\000-\037]</literal>".
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,
"<literal>[W-c]</literal>" est équivalent à
"<literal>[][\^_`wxyzabc]</literal>", avec l'option
d'insensibilité de casse. Si la table locale de
caractères est "fr", "<literal>[\xc8-\xcb]</literal>"
correspond aux caractères accentués.
</para>
<para>
Les types de caractères <literal>\d</literal>,
<literal>\D</literal>, <literal>\S</literal>, <literal>\s</literal>,
<literal>\w</literal>, <literal>\W</literal> peuvent aussi intervenir
dans les classes de caractères. Par exemple,
"<literal>[][\^_`wxyzabc][\dABCDEF]</literal>" 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
<literal>[^\W_]</literal> accepte toutes les lettres et les chiffres,
mais pas les soulignés.
</para>
<para>
Tous les caractères non alphanumériques autres que
<literal>\, -, ^</literal> (placés en début de chaîne)
et <literal>]</literal> n'ont pas de signification
particulière, mais ils ne perdront rien à être protégés.
Le délimiteur de motif est toujours spécial, et doit être
protégé lorsqu'il est utilisé à l'intérieur d'une expression.
</para>
<para>
Perl supporte la notation POSIX pour les classes de caractères.
Elles utilisent des noms entourés par <literal>[:</literal> et
<literal>:]</literal>. PCRE supporte également cette notation. Par exemple,
<literal>[01[:alpha:]%]</literal> trouve "0", "1", toute lettre,
ou encore le caractère "%". Les noms de classe supportés sont :
<table>
<title>Classes de caractères</title>
<tgroup cols="2">
<tbody>
<row>
<entry><literal>alnum</literal></entry>
<entry>lettres et chiffres</entry></row>
<row>
<entry><literal>alpha</literal></entry>
<entry>lettres</entry></row>
<row>
<entry><literal>ascii</literal></entry>
<entry>codes caractères 0 - 127</entry></row>
<row>
<entry><literal>blank</literal></entry>
<entry>espace ou tabulation uniquement</entry></row>
<row>
<entry><literal>cntrl</literal></entry>
<entry>caractères de contrôle</entry></row>
<row>
<entry><literal>digit</literal></entry>
<entry>chiffres décimaux (identique à \d)</entry>
</row>
<row>
<entry><literal>graph</literal></entry>
<entry>caractères d'impression, excluant les espaces</entry>
</row>
<row>
<entry><literal>lower</literal></entry>
<entry>lettres en minuscule</entry>
</row>
<row>
<entry><literal>print</literal></entry>
<entry>caractères d'impression, incluant les espaces</entry>
</row>
<row>
<entry><literal>punct</literal></entry>
<entry>caractères d'impression, excluant les lettres et les chiffres</entry>
</row>
<row>
<entry><literal>space</literal></entry>
<entry>espace blanc (pas tout à fait identique à \s)</entry>
</row>
<row>
<entry><literal>upper</literal></entry>
<entry>lettres en majuscule</entry>
</row>
<row>
<entry><literal>word</literal></entry>
<entry>caractères composant un mot (identique à \w)</entry>
</row>
<row>
<entry><literal>xdigit</literal></entry>
<entry>chiffres hexadécimaux</entry>
</row>
</tbody>
</tgroup>
</table>
Les caractères d'espacement (<literal>space</literal>) sont HT (9), LF (10), VT (11), FF (12), CR (13),
et l'espace (32). Notez que cette liste inclut le caractère VT (code 11). Ceci rend la classe
"space" différente de <literal>\s</literal>, qui n'inclut pas ce caractère VT (pour une raison de compatibilité
Perl).
</para>
<para>
La classe <literal>word</literal> est une extension Perl, et <literal>blank</literal>
est une extension GNU de Perl 5.8. La négation est une autre extension Perl ; elle est indiquée
par le caractère <literal>^</literal> après un double-point. Par exemple,
<literal>[12[:^digit:]]</literal> trouve "1", "2", mais aussi tout caractère qui n'est pas un chiffre.
</para>
<para>
En mode UTF-8, les caractères dont les valeurs sont supérieures à 128 ne seront trouvés par
aucune des classes de caractères POSIX.
À partir de libpcre 8.10 certains caractères de classes ont été
modifié pour utiliser des caractères de propriétés Unicode, dans ce cas les
restrictions mentionnées ne s'applique pas.
Référez-vous au <link xlink:href="&url.pcre.man;">manuel PCRE(3)</link> pour plus de détails.
</para>
<para>
Les propriétés des caractères Unicode peuvent apparaitre à l'intérieur d'une
classe de caractère. Ils ne peuvent pas faire partie d'une étendue.
Le caractère moins (tiret) après une classe de caractère Unicode satisfera littéralement.
Essayer de terminer une étendue avec une propriété de caractère Unicode résultera en un avertissement.
</para>
</section>
<section xml:id="regexp.reference.alternation">
<title>Alternatives</title>
<para>
La barre verticale <literal>|</literal> sert à séparer des
alternatives. Par exemple, dans le masque "<literal>/dupont|martin/</literal>"
recherche soit "<literal>dupont</literal>", soit "<literal>martin</literal>".
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, elles ne réussiront
que si le masque principal réussit aussi.
</para>
</section>
<section xml:id="regexp.reference.internal-options">
<title>Options internes</title>
<para>
Les options <link linkend="reference.pcre.pattern.modifiers">PCRE_CASELESS</link>,
<link linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link>,
<link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link>,
<link linkend="reference.pcre.pattern.modifiers">PCRE_UNGREEDY</link>,
<link linkend="reference.pcre.pattern.modifiers">PCRE_EXTRA</link>,
<link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link> et
PCRE_DUPNAMES peuvent être changées à l'intérieur du masque
lui-même, avec des séquences mises entre
"<literal>(?</literal>" et "<literal>)</literal>".
Les options sont :
<table>
<title>Options internes</title>
<tgroup cols="2">
<tbody>
<row>
<entry><literal>i</literal></entry>
<entry>pour <link linkend="reference.pcre.pattern.modifiers">PCRE_CASELESS</link></entry>
</row>
<row>
<entry><literal>m</literal></entry>
<entry>pour <link linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link></entry>
</row>
<row>
<entry><literal>s</literal></entry>
<entry>pour <link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link></entry>
</row>
<row>
<entry><literal>x</literal></entry>
<entry>pour <link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link></entry>
</row>
<row>
<entry><literal>U</literal></entry>
<entry>pour <link linkend="reference.pcre.pattern.modifiers">PCRE_UNGREEDY</link></entry>
</row>
<row>
<entry><literal>X</literal></entry>
<entry>Pour <link linkend="reference.pcre.pattern.modifiers">PCRE_EXTRA</link> (plus supporté à partir de PHP 7.3.0)</entry>
</row>
<row>
<entry><literal>J</literal></entry>
<entry>Pour <link linkend="reference.pcre.pattern.modifiers">PCRE_INFO_JCHANGED</link></entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
Par exemple, <literal>(?im)</literal> rend le masque insensible à
la casse, et multilignes. Il est possible d'annuler ces options en les
faisant précéder par un signe <literal>-</literal> : par
exemple <literal>(?im-sx)</literal>, ajoutera les options
<link linkend="reference.pcre.pattern.modifiers">PCRE_CASELESS</link>
et <link linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link>,
mais annulera les options
<link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link>
et <link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link>.
Si une option apparaît avant et après le signe moins, l'option
sera annulée.
</para>
<para>
Lorsqu'une modification d'option survient au degré le plus haut (et donc, pas dans
les parenthèses du sous-masque), les modifications sont appliquées dans le reste
du masque qui suit. Donc, <literal>/ab(?i)c/</literal> valide uniquement
"abc" et "abC".
</para>
<para>
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 <literal>(a(?i)b)c</literal>
acceptera <literal>abc</literal> et <literal>aBc</literal>,
mais aucune autre chaîne (en supposant que <link
linkend="reference.pcre.pattern.modifiers">PCRE_CASELESS</link> n'est pas
utilisé). Cela signifie que les options permettent d'avoir
différentes configurations de recherche pour différentes parties du masque.
Une séquence d'options dans une alternative affecte toute l'alternative.
Par exemple :
<literal>(a(?i)b|c)</literal>
accepte "<literal>ab</literal>", "<literal>aB</literal>", "<literal>c</literal>",
et "<literal>C</literal>", même si, comme dans le cas de
"<literal>C</literal>", la première alternative qui porte
l'option n'est pas prise en compte. Sinon, cela risque d'introduire
des comportements très étranges
</para>
<para>
Les options spécifiques à PCRE telles
<link linkend="reference.pcre.pattern.modifiers">PCRE_UNGREEDY</link> et
<link linkend="reference.pcre.pattern.modifiers">PCRE_EXTRA</link> peuvent
être modifiées de la même manière, en utilisant respectivement les caractères
U et X. L'option <literal>(?X)</literal> 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.
</para>
</section>
<section xml:id="regexp.reference.subpatterns">
<title>Sous-masques</title>
<para>
Les sous-masques sont délimités par des parenthèses,
et peuvent être imbriqués. Ajouter des sous-masques a deux
utilités :
</para>
<orderedlist>
<listitem>
<para>
Localiser un ensemble d'alternatives. Par exemple, le motif
<literal>cat(aract|erpillar|)</literal> trouve un des mots "cat",
"cataract", ou "caterpillar". Sans les parenthèses, cela trouverait
"cataract", "erpillar" ou la chaine vide.
</para>
</listitem>
<listitem>
<para>
Cela configure le sous-masque comme capturant. Lorsque tout le motif
correspond, la portion de la sous-chaine qui correspond au sous-masque
est passé à l'appelant grâce à l'argument <emphasis>ovector</emphasis>
de <function>pcre_exec</function>. Les parenthèses ouvrantes sont comptées
depuis la gauche vers la droite (commençant à 1) jusqu'à obtenir le nombre
des sous-masques capturants.
</para>
</listitem>
</orderedlist>
<para>
Par exemple, soit la chaîne sujet "<literal>le roi soleil</literal>"
qui est utilisée avec le masque suivant :
<literal>Le ((roi|prince) (soleil|charmant))</literal>, les sous-masques
capturés sont "<literal>roi soleil</literal>", "<literal>roi</literal>",
et "<literal>soleil</literal>", numérotés respectivement 1, 2, et 3.
</para>
<para>
L'ubiquité des parenthèses n'est pas toujours simple
d'emploi. Il y a des moments où regrouper des sous-masques
est nécessaire, sans pour autant capturer la valeur trouvée.
Si une parenthèse ouvrante est suivie de "<literal>?:</literal>",
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 "<literal>le prince charmant</literal>", utilisé
avec le masque
<literal>Le (( ?:roi|prince) (soleil|charmant))</literal>
les chaînes capturées seront "<literal>prince charmant</literal>"
et "<literal>charmant</literal>", numérotés respectivement 1
et 2. Le nombre maximal de chaînes capturées est de 65535. Il se peut qu'il
soit impossible de compiler un masque aussi large, toutefois, ceci dépend des
options de configuration de libpcre.
</para>
<para>
En guise de raccourci, si n'importe quelle option de configuration
est requise au début des sous-masques non-capturants, les lettres
d'option peuvent apparaître entre le signe <literal>"?"</literal>
et le signe <literal>":"</literal>. Ainsi, les 2 masques
</para>
<informalexample>
<programlisting>
<![CDATA[
(?i:samedi|dimanche)
(?:(?i)samedi|dimanche)
]]>
</programlisting>
</informalexample>
<para>
captureront exactement les mêmes chaînes. Du fait que les branches
alternatives sont testées de la gauche vers la droite, et que les
options ne sont pas réinitialisées tant que le sous masque n'est pas
atteint, une option de configuration d'une branche n'affecte pas
les branches sous-jacentes ; ainsi, les 2 masques ci-dessus
captureront <literal>"SAMEDI"</literal>, mais aussi
<literal>"Samedi"</literal>.
</para>
<para>
Il est possible de nommer un sous-masque en utilisant la syntaxe
<literal>(?P&lt;name&gt;pattern)</literal>. Ce sous-masque sera alors
indexé dans le tableau de concordance par sa position, ainsi
que par son nom. Il y a deux syntaxes alternatives :
<literal>(?&lt;name&gt;pattern)</literal> et
<literal>(?'name'pattern)</literal>.
</para>
<para>
Quelques fois, il est nécessaire d'avoir plusieurs correspondances en alternant
les sous groupes dans une expression régulière. Normalement, chacun recevra son
propre nombre de références arrière même si seulement un d'entre eux ne peut
correspondre. Pour éviter cela, la syntaxe <literal>(?|</literal> permet d'autoriser
les nombres dupliqués. Soit l'expression ci-après utilisée avec la chaine
<literal>Sunday</literal>:
</para>
<informalexample>
<programlisting>
<![CDATA[(?:(Sat)ur|(Sun))day]]>
</programlisting>
</informalexample>
<para>
Ici, <literal>Sun</literal> est stocké dans la référence arrière 2, alors que la référence
arrière 1 est vide. La recherche de correspondance de <literal>Saturday</literal> mène donc à
<literal>Sat</literal> dans la référence arrière 1 alors que la référence arrière 2
n'existe pas. Changer le masque en utilisant <literal>(?|</literal> résoud ce problème:
</para>
<informalexample>
<programlisting>
<![CDATA[(?|(Sat)ur|(Sun))day]]>
</programlisting>
</informalexample>
<para>
Avec ce masque, à la fois <literal>Sun</literal> et <literal>Sat</literal>
seront stockés dans la référence arrière 1.
</para>
</section>
<section xml:id="regexp.reference.repetition">
<title>Répétitions</title>
<para>
Les répétitions sont spécifiées avec
des quantificateurs, qui peuvent être placés à
la suite des caractères suivants :
<itemizedlist>
<listitem><simpara>Un caractère unique, même s'il s'agit d'un métacaractère</simpara></listitem>
<listitem><simpara>Le métacaractère . </simpara></listitem>
<listitem><simpara>Une classe de caractères</simpara></listitem>
<listitem><simpara>Une référence de retour (voir section suivante)</simpara></listitem>
<listitem><simpara>Un sous-masque avec parenthèses (à moins que ce ne soit
une assertion, voir plus loin)</simpara></listitem>
</itemizedlist>
</para>
<para>
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
<literal>z{2,4}</literal>
accepte "<literal>zz</literal>",
"<literal>zzz</literal>", ou "<literal>zzzz</literal>". L'accolade fermante
n'a pas de signification par elle-même.
Si le second nombre est omis, mais que la virgule est là, 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étitions attendues. Par exemple :
<literal>[aeiou]{3,}</literal>
accepte n'importe quelle succession d'au moins 3 voyelles minuscules, tandis
que
<literal>\d{8}</literal>
n'accepte que 8 chiffres exactement.
Une accolade ouvrante qui apparaît à une position où
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, "<literal>{,6}</literal>" n'est pas un
quantificateur, mais une chaîne de 4 caractères.
</para>
<para>
Le quantificateur {0} est autorisé, mais l'expression est alors
ignorée.
</para>
<para>
Par convenance (et pour la compatibilité ascendante), les trois
quantificateurs les plus communs ont une abréviation d'un
seul caractère :
<table>
<title>Quantificateurs sur un seul caractère</title>
<tgroup cols="2">
<tbody>
<row>
<entry><literal>*</literal></entry>
<entry>équivalent à <literal>{0,}</literal></entry>
</row>
<row>
<entry><literal>+</literal></entry>
<entry>équivalent à <literal>{1,}</literal></entry>
</row>
<row>
<entry><literal>?</literal></entry>
<entry>équivalent à <literal>{0,1}</literal></entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
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 :
<literal>(a?)*</literal>
</para>
<para>
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 où ces constructions peuvent être
utiles, ces masques sont désormais autorisés. Toutefois, si
la répétition du sous-masque ne trouve aucun caractère,
la boucle est interrompue.
</para>
<para>
Par défaut, les quantificateurs sont dits "gourmands", c'est-à-dire,
qu'ils cherchent d'abord à trouver le nombre maximal de
répétitions qui autorisent 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 <literal>/*....*/</literal> et à l'intérieur
de ces délimiteurs, les <literal>*</literal> et <literal>/</literal>
sont autorisés. Appliquer le masque
<literal>/\*.*\*/</literal>
à la chaîne
<literal>/* premier commentaire */ aucun commentaire /* second commentaire */</literal>
ne peut réussir, car le masque travaille sur toute la chaîne,
à cause de la gourmandise du caractère <literal>.*</literal>.
</para>
<para>
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
<literal>/\*.*?\*/</literal>
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.
À cause de cette ambiguïté, il peut apparaître des situations
où il faut le doubler :
<literal>\d??\d</literal>
Ce masque va tenter de lire un seul chiffre, mais le cas échéant,
il acceptera 2 chiffres pour permettre à la recherche d'aboutir.
</para>
<para>
Si l'option <link linkend="reference.pcre.pattern.modifiers">PCRE_UNGREEDY</link>
est activée, (une option qui n'est pas disponible avec Perl) alors
les quantificateurs sont non gourmands par défaut, mais peuvent être
rendu gourmands au cas par cas, en ajoutant un point d'interrogation
après. En d'autres termes, cette option inverse le comportement par
défaut.
</para>
<para>
Les quantificateurs suivis par <literal>+</literal> sont "possessifs". Ils
mangent autant de caractères que possible et ne retournent pas
pour chercher le reste du masque. <literal>.*abc</literal> trouvera
<literal>"abc"</literal>, tandis que <literal>.*+abc</literal> ne le trouvera
pas, car <literal>.*+</literal> accapare totalement la chaîne.
Les quantificateurs possessifs peuvent être utilisés pour
accélérer le traitement.
</para>
<para>
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.
</para>
<para>
Si un masque commence par <literal>.*</literal> ou <literal>.{0,}</literal>
et que l'option <link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link>
(équivalent en Perl à /s) est
activée, c'est-à-dire en autorisant le remplacement des nouvelles
lignes par un métacaractè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étacaractère
<literal>\A</literal>. Dans le cas où on sait d'avance qu'il
n'y aura pas de caractère de nouvelle ligne, activer l'option
<link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link> et commencer
le masque par <literal>.*</literal> permet d'optimiser le masque.
Alternativement, on peut utiliser <literal>^</literal> pour ancrer
explicitement le masque.
</para>
<para>
Lorsqu'un sous-masque capturant est répété, la valeur capturée est la
dernière. Par exemple, après que
<literal>(inter[net]{3}\s*)+</literal>
ait été appliqué à "<literal>internet interne</literal>",
la valeur de la chaîne capturée est "<literal>interne</literal>".
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 :
<literal>/(a|(b))+/</literal>
accepte "<literal>aba</literal>" et
la deuxième valeur capturée est "<literal>b</literal>".
</para>
</section>
<section xml:id="regexp.reference.back-references">
<title>Références arrières </title>
<para>
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édents.
</para>
<para>
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 captures
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. Une "référence arrière vers l'avant" peut avoir du sens
lorsqu'une répétition est isolée et que le sous masque à droite a participé
à l'itération précédente. Voir la section sur les
<link linkend="regexp.reference.escape">séquences d'échappements</link>
pour plus de détails à propos du nombre de chiffres qui suivent l'antislash.
</para>
<para>
La référence arrière remplace ce qui a
été capturé par un sous-masque dans le
masque courant, plutôt que remplacer le sous-masque
lui-même. Ainsi
<literal>(calme|rapide) et \1ment</literal>
trouvera "<literal>calme et calmement</literal>"
et "<literal>rapide et rapidement</literal>", mais pas
"<literal>calme et rapidement</literal>". Si la recherche tient
compte de la casse, alors la casse de la chaîne
capturée sera importante. Par exemple,
<literal>((?i)rah)\s+\1</literal>
trouve "<literal>rah rah</literal>"
et "<literal>RAH RAH</literal>", mais pas "<literal>RAH rah</literal>",
même si le sous-masque capturant initial ne tenait pas compte
de la casse.
</para>
<para>
Il peut y avoir plusieurs références arrière dans
le même sous-masque. Si un sous-masque n'a pas été
utilisé dans une recherche, alors les références
arrière échoueront. Par exemple
<literal>(a|(bc))\2</literal>
ne réussira jamais si la chaîne sujet commence par
"<literal>a</literal>" plutôt que par "<literal>bc</literal>".
Étant donné qu'il peut y avoir jusqu'à 99 références
arrière, 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 <link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link>
est activée, on peut utiliser un espace.
Sinon, un commentaire vide fait l'affaire.
</para>
<para>
Une référence arrière qui intervient à l'intérieur de
parenthèses auxquelles elle fait référence
échouera dès que le sous-masque sera utilisé. Par exemple,
<literal>(a\1)</literal>
échouera toujours. Cependant, ces
références peuvent être utiles dans les
sous-masques répétitifs. Par exemple, le masque
"<literal>(a|b\1)+</literal>" pourra convenir pour "<literal>a</literal>",
"<literal>aba</literal>", "<literal>ababba</literal>", etc.
À 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'ait 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.
</para>
<para>
La séquence d'échappement <literal>\g</literal>
peut être utilisée pour le référencement absolu et relatif des
sous-masques. Cette séquence doit être suivie par un nombre non signé
ou négatif, entouré optionnellement par des accolades. La séquence
<literal>\1</literal>, <literal>\g1</literal> et <literal>\g{1}</literal>
sont identiques. L'utilisation de ce masque avec un nombre non signé peut
aider à ne pas le confondre lors de l'utilisation de nombre suivi d'un
antislash. Cette séquence aide à distinguer les références arrière
lors de l'utilisation de caractères octales et rend également plus facile
d'avoir une référence arrière suivie par un nombre litéral, i.e.
<literal>\g{2}1</literal>.
</para>
<para>
L'utilisation de la séquence <literal>\g</literal> avec un nombre négatif
indique une référence relative. Par exemple, <literal>(foo)(bar)\g{-1}</literal>
trouvera la séquence "foobarbar" et <literal>(foo)(bar)\g{-2}</literal> trouvera
la séquence "foobarfoo". Ceci peut être pratique dans ce gros masque
comme alternative afin de conserver une trace du nombre de sous-masques
afin de référencer un sous-masque précédant spécifique.
</para>
<para>
Les références arrière du sous-masque nommé peuvent être
utilisées sous la forme
<literal>(?P=name)</literal>,
<literal>\k&lt;name&gt;</literal>, <literal>\k'name'</literal>,
<literal>\k{name}</literal>, <literal>\g{name}</literal>,
<literal>\g&lt;name&gt;</literal> ou <literal>\g'name'</literal>.
</para>
</section>
<section xml:id="regexp.reference.assertions">
<title>Assertions</title>
<para>
Une assertion est un test sur les caractères suivants ou
précédents celui qui est en cours d'étude. Ce
test ne consomme pas de caractères (ie, on ne déplace
pas le pointeur de caractères). Les assertions simples sont
codées avec <literal>\b</literal>, <literal>\B</literal>,
<literal>\A</literal>, <literal>\Z</literal>, <literal>\z</literal>,
<literal>^</literal> et <literal>$</literal>, et sont décrites
dans les <link linkend="regexp.reference.escape">séquences d'échappement</link>.
Il existe cependant des types d'assertions plus complexes, codées sous la forme
de sous-masques. Il en existe deux types : celles qui travaillent
<emphasis>au-delà</emphasis> de la position courante, et celles qui
travaillent <emphasis>en-deçà</emphasis>.
</para>
<para>
Une assertion se comporte comme un sous-masque, hormis le fait qu'elle
ne déplace pas le pointeur de position. Les <emphasis>assertions avant</emphasis>
commencent par <literal>(?=</literal> pour les assertions positives, et
par <literal>(?!</literal>, pour les assertions négatives. Par exemple :
<literal>\w+(?=;)</literal>
s'assure qu'un mot est suivi d'un point-virgule,
mais n'inclut pas le point virgule dans la capture et <literal>foo(?!bar)</literal>
trouve toutes les occurrences de "foo" qui ne sont pas suivies par "bar".
Notez que,
<literal>(?!foo)bar</literal>
en est proche, mais ne trouve pas une
occurrence de "<literal>bar</literal>" qui soit précédée
par quelque chose d'autre que "<literal>foo</literal>"; il
trouve toutes les occurrences de "<literal>bar</literal>",
quel que soit ce qui le précède, car l'assertion
<literal>(?!foo)</literal>
est toujours vraie quand les trois caractères suivants sont
"<literal>bar</literal>". Une assertion arrière est ici
nécessaire.
</para>
<para>
Les <emphasis>assertions</emphasis> arrières commencent par <literal>(?&lt;=</literal>
pour les assertions positives, et <literal>(?&lt;!</literal> pour les
assertions négatives. Par exemple :
<literal>(?&lt;!foo)bar</literal>
trouve les occurrences de "<literal>bar</literal>" qui ne sont pas
précédées par "<literal>foo</literal>". 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,
<literal>(?&lt;=bullock|donkey)</literal>
est autorisé, tandis que
<literal>(?&lt;!dogs?|cats?)</literal>
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ère. C'est une
amélioration du fonctionnement de Perl 5.005, qui impose
aux alternatives d'avoir toute la même taille. Une
assertion telle que
<literal>(?&lt;=ab(c|de))</literal>
n'est pas autorisée, car l'assertion de bas niveau (la deuxième,
ici) a deux possibilités de longueurs différentes. Pour
la rendre acceptable, il faut écrire
<literal>(?&lt;=abc|abde)</literal>
L'implémentation des assertions arrière 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ère avec des
sous-masques peut être particulièrement pratique à
fin des chaînes. Un exemple est donné à la fin de
cette section.
</para>
<para>
Plusieurs assertions peuvent intervenir successivement. Par exemple,
le masque
<literal>(?&lt;=\d{3})(?&lt;!999)foo</literal>
recherche les chaînes "<literal>foo</literal>" précédées
par trois chiffres qui ne sont pas "999". Notez que chaque assertion
est appliquée indépendamment, 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 "<literal>999</literal>". Le masque précédant
n'accepte pas "<literal>foo</literal>" précédé de
6 caractères, les trois premiers étant des chiffres et
les trois suivants étant différents de "<literal>999</literal>".
Par exemple, ce masque n'acceptera pas la chaîne
"<literal>123abcfoo</literal>". Pour ce faire, il faut utiliser le masque
suivant :
<literal>(?&lt;=\d{3}...)(?&lt;!999)foo</literal>.
</para>
<para>
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 "<literal>999</literal>".
</para>
<para>
De plus, les assertions peuvent être imbriquées :
<literal>(?&lt;=(?&lt;!foo)bar)baz</literal>
recherche les occurrences de "<literal>baz</literal>" qui sont
précédées par "<literal>bar</literal>", qui,
à son tour, n'est pas précédé par
"<literal>foo</literal>". Au contraire,
<literal>(?&lt;=\d{3}...(?&lt;!999))foo</literal>
est un autre masque, qui recherche les caractères "<literal>foo</literal>",
précédés par trois chiffres, suivis de trois
autres caractères qui ne forment pas "<literal>999</literal>".
</para>
<para>
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.
</para>
<para>
200 assertions au maximum sont autorisées.
</para>
</section>
<section xml:id="regexp.reference.onlyonce">
<title>Sous-masques uniques</title>
<para>
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.
</para>
<para>
Considérons, par exemple, le masque <literal>\d+foo</literal>
appliqué à la ligne
<literal>123456bar</literal>.
</para>
<para>
Après avoir tenté d'utiliser les 6 chiffres suivis
de "<literal>foo</literal>" 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
<literal>(?&gt;</literal> comme ceci :
<literal>(?&gt;\d+)bar</literal>
</para>
<para>
Ce type de parenthèses verrouille le sous-masque qu'il contient
une fois qu'il a été trouvé, et empêche un
échec ultérieur d'y repasser, mais autorise à
revenir plus loin en arrière.
</para>
<para>
Une autre description est que les sous-masques de ce type
recherchent les chaînes de caractères, et ancre le sous-masque
à l'intérieur de la chaîne.
</para>
<para>
Les sous-masques uniques ne sont pas capturants. Des cas simples comme
ceux présentés ci-dessus peuvent être pris comme
des situations maximales, qui réservent le maximum de
caractères. En effet, alors que <literal>\d+</literal> et
<literal>\d+?</literal> ajustent le nombre de chiffres trouvés
de manière à laisser la possibilité au masque de
réussir, <literal>(?&gt;\d+)</literal> ne peut retenir que la
séquence entière de chiffres.
</para>
<para>
Cette construction peut contenir un nombre arbitraire de sous-masques
complexes, et ils peuvent être imbriqués.
</para>
<para>
Les sous-masques uniques ne peuvent être utilisés qu'avec
les assertions arrière, pour effectuer une recherche efficace
en fin de chaîne. Considérons un masque simple tel
<literal>abcd$</literal>
appliqué à une très longue chaîne qui ne lui correspond pas.
À cause du système de recherche de gauche à droite, PCRE va
commencer par rechercher un "<literal>a</literal>" 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
<literal>^.*abcd$</literal>
alors, la séquence <literal>.*</literal> 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
"<literal>a</literal>" 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
<literal>^(?&gt;.*)(?&lt;=abcd)</literal>
alors il n'y aurait pas de retour en arrière, pour satisfaire
la séquence <literal>.*</literal>, 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 termes de performances et de temps de recherche.
</para>
<para>
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étiteurs, l'utilisation des
sous-masques à utilisation unique est la seule façon
d'éviter l'échec de la recherche après un
temps de calcul trop long.
Le masque
<literal>(\D+|&lt;\d+&gt;)*[!?]</literal>
recherche un nombre illimité de sous-chaînes, qui contiennent soit
des non-chiffres, soit des chiffres inclus dans &lt;&gt;, suivi soit
par <literal>!</literal> ou par <literal>?</literal>. Lorsqu'il trouve
une solution, ce masque va très vite. Mais, lorsqu'il est
appliqué à une chaîne telle :
<literal>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</literal>,
il lui faut beaucoup de temps pour annoncer un échec. Cela est
dû au fait que la chaîne 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
<literal>[!?]</literal> plutôt qu'un caractère simple, car
PCRE et PHP utilise une optimisation qui leur permet 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
<literal>((?&gt;\D+)|&lt;\d+&gt;)*[!?]</literal>
les séquences de chiffres ne peuvent pas être
trouvées, et l'échec intervient rapidement.
</para>
</section>
<section xml:id="regexp.reference.conditional">
<title>Les sous-masques conditionnels</title>
<para>
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
</para>
<informalexample>
<programlisting>
<![CDATA[
(?(condition)masque positif)
(?(condition) masque positif | masque négatif)
]]>
</programlisting>
</informalexample>
<para>
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 possibilités, une erreur est générée
à la compilation.
</para>
<para>
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 <link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link>
activée) et qui est divisée en trois parties
pour simplifier les explications :
</para>
<informalexample>
<programlisting>
<![CDATA[
( \( )? [^()]+ (?(1) \) )
]]>
</programlisting>
</informalexample>
<para>
La première partie recherche une parenthèse ouvrante
optionnelle et, si elle existe, elle est capturée. La deuxième
partie recherche une 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 a 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.
</para>
<para>
Si la condition est la chaîne <literal>(R)</literal>, elle sera
satisfaite si un appel récursif au masque ou au sous-masque
a été fait. Au premier appel, la condition n'est pas vérifiée.
</para>
<para>
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êmes conditions que
le précédent) et avec deux possibilités en seconde ligne :
</para>
<informalexample>
<programlisting>
<![CDATA[
(?(?=[^a-z]*[a-z])
\d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} )
]]>
</programlisting>
</informalexample>
<para>
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 présence 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 <literal>dd-aaa-dd</literal> ou
<literal>dd-dd-dd</literal>, avec "<literal>aaa</literal>" qui sont des
lettres, et <literal>dd</literal> qui sont des chiffres.
</para>
</section>
<section xml:id="regexp.reference.comments">
<title>Commentaires</title>
<para>
La séquence <literal>(?#</literal> 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.
</para>
<para>
Si l'option <link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link>
est activée, les caractères dièses
<literal>#</literal> non protégés en dehors d'une classe de
caractères introduisent un commentaire qui continuera jusqu'à
la prochaine ligne dans le masque.
</para>
<para>
<example>
<title>Usage de commentaire dans un masque PCRE</title>
<programlisting role="php">
<![CDATA[
<?php
$subject = 'test';
/* (?# can be used to add comments without enabling PCRE_EXTENDED */
$match = preg_match('/te(?# this is a comment)st/', $subject);
var_dump($match);
/* Whitespace and # is treated as part of the pattern unless PCRE_EXTENDED is enabled */
$match = preg_match('/te #~~~~
st/', $subject);
var_dump($match);
/* When PCRE_EXTENDED is enabled, all whitespace data characters and anything
that follows an unescaped # on the same line is ignored */
$match = preg_match('/te #~~~~
st/x', $subject);
var_dump($match);
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
int(1)
int(0)
int(1)
]]>
</screen>
</example>
</para>
</section>
<section xml:id="regexp.reference.recursive">
<title>Masques récursifs</title>
<para>
Considérons le cas où il faut rechercher 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'imbrication variable.
PCRE fournit un nouvel outil expérimental qui permet
d'utiliser la récursivité dans les masques (entre autres).
L'option <literal>(?R)</literal> est fournie pour servir la cause de
la récursivité. Le masque suivant résout le
problème des parenthèses (l'option
<link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link> est
utilisée pour ignorer les espaces) :
<literal>\( ( (?&gt;[^()]+) | (?R) )* \)</literal>
</para>
<para>
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.
</para>
<para>
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équences 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
à
<literal>(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()</literal>
la réponse arrive rapidement. Sinon, si les sous-chaînes
à utilisation unique ne sont pas utilisées, la
recherche peut prendre un temps très long, car il existe
de très nombreuses combinaisons de <literal>+</literal> et
<literal>*</literal> à tester avant de conclure à
l'échec.
</para>
<para>
Les valeurs utilisées pour capturer les sous-masques sont celles
utilisées par les niveaux les plus hauts de
récursivité, auxquels la valeur est fixée.
Si le masque précédent est utilisé avec
<literal>(ab(cd)ef)</literal>
la valeur de la parenthèse capturante est "<literal>ef</literal>",
qui est la dernière valeur lue au niveau supérieur. Si de nouvelles
parenthèses sont ajoutées, par exemple :
<literal>\( ( ( (?&gt;[^()]+) | (?R) )* ) \)</literal>
alors la chaîne capturée est "<literal>ab(cd)ef</literal>",
c'est-à-dire le contenu de la parenthèse capturante
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 dans le cadre d'une récursivité.
</para>
<para>
<literal>(?1)</literal>, <literal>(?2)</literal> et suivants
peuvent être également utilisés pour les sous masques récursifs. Il est également
possible d'utiliser les sous masques nommés : <literal>(?P&gt;foo)</literal> ou
<literal>(?&amp;name)</literal>.
</para>
<para>
Si la syntaxe pour une référence de sous-masque récursif (soit par un
nombre ou par un nom) est utilisée en dehors des parenthèses à laquelle
elle fait référence, il opère comme une sous-routine dans un langage
de programmation. Un exemple ci-dessus a montré que le masque
<literal>(sens|respons)e and \1ibility</literal>
trouvera <literal>"sense and sensibility"</literal> et
<literal>"response and responsibility"</literal>, mais pas
<literal>"sense and responsibility"</literal>. Si on utilise plutôt le masque
<literal>(sens|respons)e and (?1)ibility</literal>
alors, il trouvera <literal>"sense and responsibility"</literal>
tout comme les deux autres chaînes.
De telles références doivent, dépendant, suivre le sous-masque auquel
elles se réfèrent.
</para>
<para>
La longueur maximale d'un sujet correspond au plus grand nombre positif
qu'une variable entière peut contenir. Cependant, PCRE utilise la récursivité
pour gérer les sous-masques et les répétitions infinies. Ce qui signifie
que l'espace disponible pour la pile peut limiter la taille du sujet qui peut
être passé à certains masques.
</para>
</section>
<section xml:id="regexp.reference.performance">
<title>Performance</title>
<para>
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 <literal>[aeiou]</literal> plutôt qu'une alternative
<literal>(a|e|i|o|u)</literal>.
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.
</para>
<para>
Lorsqu'un masque commence par.* et que l'option
<link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link> 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 l'option
<link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link> n'est pas
activée, PCRE ne peut faire aucune optimisation, car le
métacaractère point "<literal>.</literal>"
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,
<literal>(.*)second</literal>
acceptera la chaîne "<literal>premier \net second</literal>"
(avec "<literal>\n</literal>" qui remplace la nouvelle ligne),
et la première chaîne capturée sera "<literal>et</literal>".
Afin d'effectuer la recherche, PCRE va essayer d'appliquer le masque
à partir de chaque début de ligne.
</para>
<para>
Si vous utilisez un tel masque avec des chaînes qui ne contiennent
pas de caractères de nouvelle ligne, les meilleures performances
seront atteintes avec l'option
<link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link>, ou en ancrant le
masque avec <literal>^.*</literal>. Cela évite à PCRE
de scanner toute la chaîne pour rechercher un caractère
de nouvelle ligne et recommencer la recherche.
</para>
<para>
Attention aux masques qui contiennent des quantificateurs infinis
imbriqués. Ils peuvent demander un temps de calcul très
long, lorsque appliqués à une chaîne qui ne
correspond pas à ce masque. Par exemple,
<literal>(a+)*</literal>
</para>
<para>
Ce masque peut accepter "<literal>aaaa</literal>" de 33 manières
différentes, et ce nombre croit rapidement avec la taille
de la chaîne (le quantificateur <literal>*</literal> peut prendre
les valeurs de 0, 1, 2, 3, ou 4, et pour chaque cas non nul, le
quantificateur <literal>+</literal> 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.
</para>
<para>
Un optimiseur repère les cas les plus simples, tel que
<literal>(a+)*b</literal>
où un caractère simple suit les quantificateurs.
Avant de partir dans les procédures standards de recherche, PCRE
s'assure qu'il y a au moins un "<literal>b</literal>" 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 :
<literal>(a+)*\d</literal>.
Le premier retourne un échec quasi-immédiatement, s'il est appliqué à
une ligne de "<literal>a</literal>", alors que le second masque
prend un temps significatif pour une chaîne de plus de
20 caractères.
</para>
</section>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->