Quiz Regex no 1

Et la couleur fut.
  EN, EO
 Lecture : 3 min
 chop
 Pas encore commenté
 

Il est temps de répondre au quiz Regex no 1. La regex était la suivante :

\[(#[a-fA-F0-9]{3,6}|[a-zA-Z]+)\](.+)\[\/\1\]

Comment peut-elle être utilisée ? C’est ce que nous allons expliquer dans ce billet.

Décortiquons la regex #

Le quiz donnait un indice : un matcher est nécessaire à son utilisation, ce qui indique probablement qu’on ne se contentera pas de tester si le texte en entrée respecte la regex.1

Le quiz (corrigé)

Attardons-nous sur cette regex un instant.

Échappement des crochets #

En premier lieu, on remarque que l’expression est assez désagréable à la lecture en raison de nombreux échappements, notamment des crochets : [ et ] sont précédés de \, ce que signifie qu’ils n’ont pas leur rôle standard dans une expression régulière, mais qu’ils font partie des caractères recherchés dans le texte que nous testerons.2

Groupes capturants #

On voit également deux groupes capturants :

  • Le groupe no 1 est (#[a-fA-F0-9]{3,6}|[a-zA-Z]+), il capturera :
    • soit # suivi d’une chaîne hexadécimale de 3 à 6 caractères ;
    • soit une chaîne de lettres.
  • Le groupe no 2 est (.+), il capturera tout ce qui se situera entre les ] et [ capturés.

Réutilisation d’un groupe capturé #

Petite particularité qui ne saute pas nécessairement aux yeux mais qui est fondamentale à la compréhension de cette regex : \1 permet de s’assurer que cette regex ne fonctionnera que si le texte à cette place est le même que ce qui a été capturé par le groupe no 1.

Par exemple, si le groupe 1 capture cyan, la regex ne retournera un résultat positif que si le texte à la place de \1 est cyan. Cela signifierait que l’entrée commence par [cyan] et se termine par [/cyan]. Oui, c’est un système de balises.

L’heure du bilan #

Pour résumer, nous avons donc :

  • un système de balises ;
  • la balise contient une couleur HTML, soit sous sa forme hexadécimale ou nominale ;
  • un contenu.

Oui, vous avez deviné, il s’agit d’un système de balises pour transformer [red]This is important.[/red] en <span style="color: red">This is important.</red>. Un rapide exemple de code montrant comment l’exploiter serait le suivant :

 1final String regex = "\\[(#[a-fA-F0-9]{3,6}|[a-zA-Z]+)\\](.+)\\[\\/\\1\\]";
 2final String input = "[red]This is important.[/red]";
 3
 4Pattern pattern = Pattern.compile(regex);
 5Matcher matcher = pattern.matcher(input);
 6
 7if (matcher.find()) {
 8    String output = String.format(
 9        "<span style=\"color: %s\">%s</span>",
10        matcher.group(1),
11        matcher.group(2)
12    );
13    System.out.println(output);
14} else {
15    System.out.println(input);
16}

La petite histoire #

Vous l’avez certainement compris, nos utilisateurs avaient besoin de pouvoir mettre en valeur certaines parties d’un texte avec de la couleur, dans un éditeur qui manipulait uniquement du texte brut. Les souvenirs de phpBB sont revenus et une regex a rapidement été imaginée pour répondre au besoin en se basant sur un système le plus simple possible.

C’est une utilisation plutôt simple, mais un bel exemple de l’usage de \1 pour réutiliser un groupe capturé. Dans notre cas, cela permet d’utiliser des balises au sein des balises en cas de besoin ([red]This is [#ff9900]very[/#ff9900] important.[/red]), mais d’autres cas sont moins triviaux. Nous en verrons un lors de notre prochain quiz, dans deux mois. En espérant que vous vous en souviendrez et le repèrerez.


  1. Le quiz contenait également une erreur. Lorsque l’on utilise Java, il faut échapper les échappements, ce que j’avais oublié et qui complique la lecture. Afin de se concentrer sur la regex, j’éviterai Java à l’avenir. ↩︎

  2. On pourrait ne pas échapper les crochets fermants ] afin de faciliter la lecture. \[(#[a-fA-F0-9]{3,6}|[a-zA-Z]+)](.+)\[\/\1] est ainsi équivalente. ↩︎