her.esy.fun/src/Scratch/fr/blog/2010-02-16-All-but-something-regexp--2-/index.html
Yann Esposito (Yogsototh) 059fabd7d0
many minor details to update
2022-10-26 11:38:50 +02:00

149 lines
9.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>YBlog - Tout sauf quelquechose en expression régulière.</title>
<meta name="keywords" content="regexp, regular expression" />
<link rel="shortcut icon" type="image/x-icon" href="../../../../Scratch/img/favicon.ico" />
<link rel="stylesheet" type="text/css" href="../../../../css/y.css" />
<link rel="stylesheet" type="text/css" href="/css/legacy.css" />
<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="apple-touch-icon" href="../../../../Scratch/img/about/FlatAvatar@2x.png" />
<!--[if lt IE 9]>
<script src="http://ie7-js.googlecode.com/svn/version/2.1(beta4)/IE9.js"></script>
<![endif]-->
<!-- IndieAuth -->
<link href="https://twitter.com/yogsototh" rel="me">
<link href="https://github.com/yogsototh" rel="me">
<link href="mailto:yann.esposito@gmail.com" rel="me">
<link rel="pgpkey" href="../../../../pubkey.txt">
</head>
<body lang="fr" class="article">
<div id="content">
<div id="header">
<div id="choix">
<span id="choixlang">
<a href="../../../../Scratch/en/blog/2010-02-16-All-but-something-regexp--2-/">Anglais</a>
</span>
<span class="tomenu"><a href="#navigation">↓ Menu ↓</a></span>
<span class="flush"></span>
</div>
</div>
<div id="titre">
<h1>Tout sauf quelquechose en expression régulière.</h1>
</div>
<div class="flush"></div>
<div id="afterheader" class="article">
<div class="corps">
<p>Dans mon <a href="../../../../Scratch/fr/blog/2010-02-15-All-but-something-regexp">précédent article</a> jai donné certaines astuces pour matcher tout sauf quelque chose. De la même manière, un truc pour matcher la chaine de caractère la plus petite possible. Disons que vous voulez matcher la chaine de caractère entre a et b. Par exemple, vous voulez matcher&nbsp;:</p>
<pre class="twilight">
a.....<strong class="blue">a......b</strong>..b..a....<strong class="blue">a....b</strong>...
</pre>
<p>Voici les deux erreurs communes et une solution&nbsp;:</p>
<pre>
/a.*b/
<strong class="red">a.....a......b..b..a....a....b</strong>...
</pre>
<p>La première erreur vient de lutilisation du <em>terrible</em> <code>.*</code>. Parce que vous allez matcher la chaîne de caractère la plus longue possible.</p>
<pre>
/a.*?b/
<strong class="red">a.....a......b</strong>..b..<strong class="red">a....a....b</strong>...
</pre>
<p>Lautre manière naturelle de répondre à ce problème est de changer la <em>greediness</em>. Mais ce nest pas assez parce que vous allez matcher du premier <code>a</code> au premier <code>b</code> après celui-ci. On peut alors constater que votre chaine de caractère ne devrait comprendre ni la lettre <code>a</code> ni la lettre <code>b</code>. Ce qui emène à la dernière solution élégante.</p>
<pre>
/a[^ab]*b/
a.....<strong class="blue">a......b</strong>..b..a....<strong class="blue">a....b</strong>...
</pre>
<p>Jusquici, cétait facile. Maintenant comment fait vous quand au lieu de <code>a</code> vous avez une chaine de caractère ?</p>
<p>Par exemple, vous voulez matcher:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb1-1" title="1"><span class="kw">&lt;li&gt;</span>...<span class="kw">&lt;li&gt;</span></a></code></pre></div>
<p>Cest un peu difficile. Vous devez matcher</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb2-1" title="1"><span class="kw">&lt;li&gt;</span>[anything not containing <span class="kw">&lt;li&gt;</span>]<span class="kw">&lt;/li&gt;</span></a></code></pre></div>
<p>La première méthode serait dutiliser le même rainsonnement que dans mon <a href="../../../../Scratch/fr/blog/2010-02-15-All-but-something-regexp">article précédent</a>. Ici un premier essai&nbsp;:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode perl"><code class="sourceCode perl"><a class="sourceLine" id="cb3-1" title="1">&lt;li&gt;([^&lt;]|&lt;[^l]|&lt;l[^i]|&lt;li[^&gt;])<span class="dt">*&lt;</span><span class="kw">/</span><span class="ot">li&gt;</span></a></code></pre></div>
<p>Mais il y a encore une erreur. Pensez à la chaine de caractère suivante&nbsp;:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode html"><code class="sourceCode html"><a class="sourceLine" id="cb4-1" title="1"><span class="kw">&lt;li&gt;</span>...<span class="kw">&lt;li</span><span class="er">&lt;/li</span><span class="kw">&gt;</span></a></code></pre></div>
<p>Cette chaine ne matchera pas. Cest pourquoi si on veut vraiment la matcher correctement<sup><a href="#note1"></a></sup> nous devons ajouter&nbsp;:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode perl"><code class="sourceCode perl"><a class="sourceLine" id="cb5-1" title="1">&lt;li&gt;([^&lt;]|&lt;[^l]|&lt;l[^i]|&lt;li[^&gt;])*(|&lt;|&lt;l|&lt;li)&lt;/li&gt;</a></code></pre></div>
<p>Oui, cest un peu compliqué. Mais que se passe til lorsque la chaine de caractère que vous voulez matcher est encore plus longue que <code>&lt;li&gt;</code> ?</p>
<p>Voici un algorithme qui permet de résoudre ce problème aisément. Vous devez réduire ce problème au premier. Cest-à-dire celui avec une seule lettre&nbsp;:</p>
<pre><code># transforme un simple caractère choisi aléatoirement
# en un identifiant unique
# (vous devez vérifier que l'identifier est VRAIMENT unique)
# attention l'identifiant unique ne doit pas
# contenir le caractère choisi.
s/X/_was_x_/g
s/Y/_was_y_/g
# transforme la longue chaine de caractère
# en un seul caractère
s/&lt;li&gt;/X/g
s/&lt;\/li&gt;/Y/g
# Utilisation de la première méthode
s/X([^X]*)Y//g
# Retransformation des lettres en chaines
# de caractères
s/X/&lt;li&gt;/g
s/Y/&lt;\/li&gt;/g
# retour des anciens caractères.
s/_was_x_/X/g
s/_was_y_/Y/g</code></pre>
<p>Et ça fonctionne en seulement 9 lignes pour toute chaine de début et de fin. Cette solution fait un peu moins <em>I AM THE GREAT REGEXP M45T3R, URAN00B</em>, mais elle est mieux adaptée à mon avis. De plus, utiliser cette dernière solution prouve que vous maitrisez les expressions régulières. Simplement parce que vous savez quil est difficile de résoudre des problèmes de cette forme en utilisant seulement des expressions régulières.</p>
<hr />
<p><small><a name="note1"><sup></sup></a> Je sais que jai utilisé une syntaxe HTML dans mon exemple. Mais dans lutilisation réelle que jen ai faite, je devais matcher entre <code>en:</code> et <code>::</code>, sachant que parfois les chaines pouvaient se terminer par <code>e::</code>. </small></p>
</div>
<div id="afterarticle">
<div id="social">
<a href="/rss.xml" target="_blank" rel="noopener noreferrer nofollow" class="social">RSS</a>
·
<a href="https://twitter.com/home?status=http%3A%2F%2Fyannesposito.com/Scratch/fr/blog/2010-02-16-All-but-something-regexp--2-/%20via%20@yogsototh" target="_blank" rel="noopener noreferrer nofollow" class="social">Tweet</a>
·
<a href="http://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Fyannesposito.com/Scratch/fr/blog/2010-02-16-All-but-something-regexp--2-/" target="_blank" rel="noopener noreferrer nofollow" class="social">FB</a>
<br />
<a class="message" href="../../../../Scratch/fr/blog/Social-link-the-right-way/">Ces liens sociaux préservent votre vie privée</a>
</div>
<div id="navigation">
<a href="../../../../">Accueil</a>
<span class="sep">¦</span>
<a href="../../../../Scratch/fr/blog">Blog</a>
<span class="sep">¦</span>
<a href="../../../../Scratch/fr/softwares">Logiciels</a>
<span class="sep">¦</span>
<a href="../../../../Scratch/fr/about">Auteur</a>
</div>
<div id="totop"><a href="#header">↑ Top ↑</a></div>
<div id="bottom">
<div>
Published on 2010-02-16
</div>
<div>
<a href="https://twitter.com/yogsototh">Follow @yogsototh</a>
</div>
<div>
<a rel="license" href="http://creativecommons.org/licenses/by/3.0/deed.en_US">Yann Esposito©</a>
</div>
<div>
Done with
<a href="http://www.vim.org" target="_blank" rel="noopener noreferrer nofollow"><strike>Vim</strike></a>
<a href="http://spacemacs.org" target="_blank" rel="noopener noreferrer nofollow">spacemacs</a>
<span class="pala">&amp;</span>
<a href="http://nanoc.ws" target="_blank" rel="noopener noreferrer nofollow"><strike>nanoc</strike></a>
<a href="http://jaspervdj.be/hakyll" target="_blank" rel="noopener noreferrer nofollow">Hakyll</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>