<h3>Introduction</h3>
<p class="spip">Les expressions rationnelles (<i class="spip">regular expressions</i>) sont un moyen très puissant de faire des recherches et des séléctions sur du texte. Concretement ce sont des chaînes de caractères contenant des marqueurs et différents caractères spéciaux des sortes de jokers, qui definissent à quoi une expression rationnelle doit correspondre.</p>

<p class="spip">On dit qu’une expression rationnelle correspond (<i class="spip">match</i>) à une chaîne lorsque cette chaîne répond aux critères de l’expression (<i class="spip">pattern</i>).</p>

<p class="spip">Même si les expressions rationnelles paraissent compliquées, illisibles et rébarbatives, la syntaxe est suffisemment accessible et avec un peu de pratique vous verrez le temps gagné par rapport à l’utilisation des nombreuses fonctions textuelles classiques (<i class="spip">strpos, strchr, str_replace...</i>).</p>

<h3>I. Commençons par le début...</h3>
<p class="spip">Les exemples de cette partie sont tous faits avec l’utilitaire GNU <i class="spip">grep</i>, (voir à la fin pour les fichiers d’exemples).</p>

<p class="spip">La bonne nouvelle c’est que l’expression régulière "toto" correspond à la chaîne "toto" !</p>

<p class="spip"><strong class="spip">Exemple 1.1 :</strong></p>

<p class="spip"><code class='spip_code' dir='ltr'>$ grep --color toto 1.1</code>
<br/><font color="red">toto</font> va l’école<br/>
le meilleur c’est <font color="red">toto</font></p>

<p class="spip"><strong class="spip">Explication :</strong> grep <i class="spip">options</i> expression_rationnelle <i class="spip">fichier</i>
grep affiche toutes les lignes du fichier passé en paramètre (ou de l’entrée standard) qui contiennet au moins une correspondance à l’exprression rationnelle passée en paramètre. L’option &mdash;color permet de mettre en surbrillance le texte qui correspond à l’expression rationnelle.</p>

<p class="spip">Voici les deux premiers marqueurs auxquels nous allons nous intéresser : ^ lorsqu’il est placé devant l’expression rationnelle, signifie que la corresondance doit débuter la chaîne, le $ lorsqu’il se trouve à la fin de l’expression rationnelle, signifie que la corresponance doit clore la chaîne de caractères.</p>

<p class="spip"><strong class="spip">Exemple 1.2 :</strong></p>

<p class="spip"><code class='spip_code' dir='ltr'>$ grep --color '^toto' 1.1</code>
<br/><font color="red">toto</font> va l’école</p>

<p class="spip"><strong class="spip">Exemple 1.3 :</strong></p>

<p class="spip"><code class='spip_code' dir='ltr'>$ grep --color 'toto$' 1.1</code>
<br/>le meilleur c’est <font color="red">toto</font></p>

<p class="spip"><strong class="spip">Explication :</strong> lorsque l’expression régulière contient des espaces ou des caractères spéciaux, il est conseillé de la mettre entre guimmet simples ou doubles (qu’il faudra échapper d’un slash à l’ntérieur de l’expression rationnelle.</p>

<p class="spip">Donc la seule chaîne pouvant contenir une correspondance à l’expression ’^toto$’ est la chaîne "toto".</p>

<p class="spip"><strong class="spip">Remarque :</strong> <i class="spip">grep</i> considère chaque ligne comme une nouvelle chaîne à analyser, à chaque ligne on retrouve donc un ^ au début et un $ à la fin.</p>

<h3>II. Jokers et listes</h3>
<p class="spip">Le point . a un sens particulier dans les expressions régulières : il représente un caractère quelconque, si vous souhaitez trouver un point avec une expression rationnelle, il faudra l’échapper ou l’entourer de crochets [.].</p>

<p class="spip"><strong class="spip">Exemple 2.1 :</strong></p>

<p class="spip"><code class='spip_code' dir='ltr'>$ grep --color 't.t.' 2.1</code>
<br/><font color="red">toto</font><br/>
<font color="red">tata</font><br/>
<font color="red">tito</font></p>

<p class="spip">De ce fait il faut faire attention dans vos scripts shell, dans le classique <i class="spip">... | grep truc.com</i> le point ne représente pas le point mais n’importe quoi !</p>

<p class="spip">les crochets [ ... ] définissent une liste de caractères recherchés, ’[aou]’ correspond à ’a’, ’o’ ou ’u’. On peut aussi définir une rangée de caractères avec un tiret - : [a-z], [0-9]... Si vous voulez placer un tiret dans une liste sans son sens particulière, il faut le mettre en début de la liste : [-A-Z] correspond à un caractère de A à Z ou à un tiret. Les rangées définies avec le tiret se font par les codes numériques des caractères alors il faut faire très attention à ce qu’on y met au risque d’avoir des résultat imprévisibles.</p>

<p class="spip"><strong class="spip">Exemple 2.2 :</strong></p>

<p class="spip"><code class='spip_code' dir='ltr'>$ grep --color 't[oi]' 2.1</code>
<br/><font color="red">to</font>to<br/>
<font color="red">ti</font>to<br/></p>

<p class="spip">La norme POSIX propose pas mal de listes prédéfinies ce qui allège pas mal les expressions rationnelles :</p>

<table class="spip">
<tbody>
<tr class="row_even"><td>[:alnum :]</td><td>caractères alphanumériques (équivalent à [A-Za-z0-9])</td></tr>
<tr class="row_odd"><td>[:alpha :]</td><td>caractères alphabétiques ([A-Za-z])</td></tr>
<tr class="row_even"><td>[:blank :]</td><td>caractères blanc (espace, tabulation)</td></tr>
<tr class="row_odd"><td>[:ctrl :]</td><td>caractères de contrôle (les premiers du code ASCII)</td></tr>
<tr class="row_even"><td>[:digit :]</td><td>chiffre ([0-9])</td></tr>
<tr class="row_odd"><td>[:graph :]</td><td>caractère d’imprimerie (qui fait une marque sur l’écran en quelque sorte)</td></tr>
<tr class="row_even"><td>[:print :]</td><td>caractère imprimable (qui passe à l’imprimante ... tout sauf les caractères de contrôle)</td></tr>
<tr class="row_odd"><td>[:punct :]</td><td>caractère de ponctuation</td></tr>
<tr class="row_even"><td>[:space :]</td><td>caractère d’espacement</td></tr>
<tr class="row_odd"><td>[:upper :]</td><td>caractère majuscule</td></tr>
<tr class="row_even"><td>[:xdigit :]</td><td>caractère hexadécimal</td></tr>
</tbody>
</table>
<p class="spip"><strong class="spip">Attention :</strong> [:alpha :] ou [a-zA-Z] n’inclut pas les caractères accentués français !</p>

<p class="spip"><strong class="spip">Attention :</strong> certaines implémentations des expressions régulières (notamment le PHP) n'acceptent pas [:classe_posix:] en tant que liste valide mais comme un élément de liste, il faudra utiliser [[:classe:]...]</p>

<p class="spip">On peut faire une liste avec négation en plaçant ^ comme premier élément, cela voudra dire que tout caractère est accepté sauf ceux listés.</p>

<p class="spip"><strong class="spip">Exemple 2.3 :</strong></p>

<p class="spip"><code class='spip_code' dir='ltr'>$ grep --color 't[^a]' 2.1</code>
<br/><font color="red">to</font>to <br/>
<font color="red">ti</font>to<br/>
<font color="red">tu</font>x</p>

<p class="spip">Ces nouveaux jouets donnent de nouveaux caractères à échapper si vous ne voulez pas les utiliser avec leur sens spécial [ s'écrira [[], ] []] et ^ [^]. Ca marche même dans des listes!</p>

<p class="spip"><strong class="spip">III. Les quantifieurs</strong></p>

<p class="spip">Un autre aspect très import est de définir combien de fois on veut voir un caractère (ou une des possibilités d’une liste) répété. Par défaut chaque caractère à un quantifieur 1. :)</p>

<p class="spip">Un quantifieur suit le caractère et se place entre accolades  { } : on peut y mettre un chiffre, ou une rangée de chiffres... voici quelques exemples :
'a{2}' correspond à deux lettres 'a' consecutives, donc à l'expression 'aa'
'ab{2,4}' signifie qu'on veut un 'a' suivi de 2, 3 ou 4 lettres 'b'.
'ab{2,}' signifie qu'on veut un 'a' suivi de 2 'b' ou plus.</p>

<p class="spip">Certains quatifieurs très utilisés ont des noms plus courts (il faudra les échapper !) :</p>

<p class="spip">|*|zéro ou plusieurs|
| ?|zéro ou un| 
|+|un ou plusieurs|</p>

<p class="spip"><strong class="spip">Exemple 3.1 :</strong></p>

<p class="spip"><code class='spip_code' dir='ltr'>$ grep --color 'a\{2,\}' 3.1</code>
<br/><font color="red">abbb</font></p>

<p class="spip"><strong class="spip">Explications :</strong> par defaut grep utilise les expressions regulières POSIX dites de base (BRE),  en BRE pour que les accolades, les parenthèses et les ’pipes’ | prennent leur sens spécial il faudra les échapper. Si cela alourdit trop les expressions, vous pouvez forcer grep à utiliser les expression POSIX étendues ERE avec l’option -E ou alors en utilisant egrep qui est un alias de grep -E et ne plus avoir à les échapper.</p>

<p class="spip">Ces quantifieurs posent un problème qu’est la "gourmandise" des expressions régulières, dans l’exemple on voit qu’il suffit 2 ’b’ alors que tous les 3 correspondent, il y a donc deux possibilités de correspondance ’abb’ et ’abbb’. La norme POSIX dit que la gourmandise est maximale. Ca signifie concrètement que si plusieurs correspondances sont possibles, c’est la plus longue qui est prise.</p>

<p class="spip"><strong class="spip">IV. Les ancres et les références</strong></p>

<p class="spip">On définit un ancre avec des parenthèses ( ... ), en encadrant une partie de l’expression régulière d’un ancre, on peut y faire référence soit dans l’expression rationnelle même (backreference) soit dans une chaîne de remplacement avec des outils tels que sed . Pour faire un référence on échappe simplement son numéro d’un backslash : l’ancre 0 correspond à toute la correspondance (très dangereux pour une backrefrence car peut engendrer une boucle récursive infinie), 1 à la première parenthèse ouverte etc...</p>

<p class="spip"><strong class="spip">Exemple 4.1 :</strong>
<code class='spip_code' dir='ltr'>$ grep --color 't\(.\)t\1' 2.1</code>
<br/><font color="red">toto<br/>
tata</font></p>

<p class="spip"><strong class="spip">Explication :</strong> On cherche des correspondances avec ’t’, n’importe quelle lettre, ’t’ la même lettre que celle d’avant : ’toto’ et ’tata’ correspondent mais pas ’tito’.</p>

<p class="spip">Les parenthèses permettent également de donner des variantes d’une expression rationnelle ou d’une partie de l’expression régulière (expression1|expression2|expressionN...).</p>

<p class="spip"><strong class="spip">Exemple 4.2 :</strong></p>

<p class="spip"><code class='spip_code' dir='ltr'>$ grep -E --color 't(o|x)(to|x)' 2.1</code>
<br/><font color="red">toto<br/>
tux</font></p>

<p class="spip">J’ai volontairement utilisé grep -E pour montrer qu’avec -E il ne faut pas échapper les parenthèses et les |.</p>

<p class="spip">If faut savoir que presque toutes les implémentations des expressions rationnelles utilisent maintenant les ERE par défaut, il est donc conseillé sous shell d’utiliser egrep lorsqu’on veut effectuer des recherches par expression rationnelle et grep pour des recherches de simple texte (en n’oubliant pas d’échapper les points pour qu’ils perdent leur sens spécial).</p>

<p class="spip"><strong class="spip">Remarque :</strong> On peut aussi placer un quantifieur à un groupe entre parenthèses.</p>

<h3>Les fichiers des exemples</h3>
<p class="spip"><strong class="spip"> 1.1 </strong></p>

<p class="spip">toto va l'école<br/>
le meilleur c'est toto</p>

<p class="spip"><strong class="spip"> 2.1 </strong></p>

<p class="spip">toto<br/>
tata<br/>
tito<br/>
tux</p>

<p class="spip"><strong class="spip"> 3.1 </strong></p>

<p class="spip">abbb</p>