265 lines
16 KiB
HTML
265 lines
16 KiB
HTML
|
<?xml version="1.0" encoding="utf-8"?>
|
||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr">
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||
|
|
||
|
|
||
|
<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="/Scratch/assets/css/main.css" />
|
||
|
<link rel="stylesheet" type="text/css" href="/Scratch/css/twilight.css" />
|
||
|
<link rel="stylesheet" type="text/css" href="/Scratch/css/idc.css" />
|
||
|
<link rel="alternate" type="application/rss+xml" title="RSS" href="http://feeds.feedburner.com/yannespositocomfr"/>
|
||
|
|
||
|
<link rel="alternate" lang="fr" xml:lang="fr" title="Tout sauf quelquechose en expression régulière." type="text/html" hreflang="fr" href="/Scratch/fr/blog/2010-02-16-All-but-something-regexp--2-/" />
|
||
|
<link rel="alternate" lang="en" xml:lang="en" title="Pragmatic Regular Expression Exclude (2)" type="text/html" hreflang="en" href="/Scratch/en/blog/2010-02-16-All-but-something-regexp--2-/" />
|
||
|
<script type="text/javascript" src="/Scratch/js/jquery-1.3.1.min.js"></script>
|
||
|
<script type="text/javascript" src="/Scratch/js/jquery.cookie.js"></script>
|
||
|
<script type="text/javascript" src="/Scratch/js/index.js"></script>
|
||
|
|
||
|
<title>Tout sauf quelquechose en expression régulière.</title>
|
||
|
</head>
|
||
|
<body lang="fr">
|
||
|
<script type="text/javascript">// <![CDATA[
|
||
|
document.write('<div id="blackpage"><img src="/Scratch/img/loading.gif" alt="Chargement en cours..."/></div>');
|
||
|
// ]]>
|
||
|
</script>
|
||
|
|
||
|
<div id="content">
|
||
|
<div id="choix">
|
||
|
<div class="return"><a href="#entete">↓ Menu ↓</a></div>
|
||
|
<div id="choixlang">
|
||
|
<a href="/Scratch/en/blog/2010-02-16-All-but-something-regexp--2-/" onclick="setLanguage('en')">Switch to English</a>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div id="titre">
|
||
|
<h1>
|
||
|
Tout sauf quelquechose en expression régulière.
|
||
|
</h1>
|
||
|
|
||
|
</div>
|
||
|
|
||
|
<div class="flush"></div>
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
<div class="flush"></div>
|
||
|
<div id="afterheader">
|
||
|
<div class="corps">
|
||
|
<p>Dans mon <a href="previouspost">précédent article</a> j’ai 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 :</p>
|
||
|
|
||
|
<pre class="twilight">
|
||
|
a.....<span class="Constant"><strong>a......b</strong></span>..b..a....<span class="Constant"><strong>a....b</strong></span>...
|
||
|
</pre>
|
||
|
|
||
|
<p>Voici les deux erreurs communes et une solution :</p>
|
||
|
|
||
|
<pre class="twilight">
|
||
|
/a.*b/
|
||
|
<span class="Constant"><strong>a.....a......b..b..a....a....b</strong></span>...
|
||
|
</pre>
|
||
|
|
||
|
<p>La première erreur vient de l’utilisation du <em>terrible</em> <code>.*</code>. Parce que vous allez matcher la chaîne de caractère la plus longue possible.</p>
|
||
|
|
||
|
<pre class="twilight">
|
||
|
/a.*?b/
|
||
|
<span class="Constant"><strong>a.....a......b</strong></span>..b..<span class="Constant"><strong>a....a....b</strong></span>...
|
||
|
</pre>
|
||
|
|
||
|
<p>L’autre manière naturelle de répondre à ce problème est de changer la <em>greediness</em>. Mais ce n’est 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 class="twilight">
|
||
|
/a[^ab]*b/
|
||
|
a.....<span class="Constant"><strong>a......b</strong></span>..b..a....<span class="Constant"><strong>a....b</strong></span>...
|
||
|
</pre>
|
||
|
|
||
|
<p>Jusqu’ici, 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><pre class="twilight">
|
||
|
<li>...<li>
|
||
|
</pre></div>
|
||
|
|
||
|
<p>C’est un peu difficile. Vous devez matcher</p>
|
||
|
<div><pre class="twilight">
|
||
|
<li>[anything not containing <li>]</li>
|
||
|
</pre></div>
|
||
|
|
||
|
<p>La première méthode serait d’utiliser le même rainsonnement que dans mon <a href="previouspost">article précédent</a>. Ici un premier essai :</p>
|
||
|
|
||
|
<div><pre class="twilight">
|
||
|
<li>([^<]|<[^l]|<l[^i]|<li[^>])*</li>
|
||
|
</pre></div>
|
||
|
|
||
|
<p>Mais il y a encore une erreur. Pensez à la chaine de caractère suivante :</p>
|
||
|
<div><pre class="twilight">
|
||
|
<li>...<li</li>
|
||
|
</pre></div>
|
||
|
|
||
|
<p>Cette chaine ne matchera pas. C’est pourquoi si on veut vraiment la matcher correctement<sup><a href="#note1">†</a></sup> nous devons ajouter :</p>
|
||
|
<div><pre class="twilight">
|
||
|
<li>([^<]|<[^l]|<l[^i]|<li[^>])*(|<|<l|<li)</li>
|
||
|
</pre></div>
|
||
|
|
||
|
<p>Oui, c’est un peu compliqué. Mais que se passe t’il lorsque la chaine de caractère que vous voulez matcher est encore plus longue que <code><li></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. C’est-à-dire celui avec une seule lettre :</p>
|
||
|
|
||
|
<div><pre class="twilight">
|
||
|
<span class="Comment"><span class="Comment">#</span> transforme un simple caractère choisi aléatoirement</span>
|
||
|
<span class="Comment"><span class="Comment">#</span> en un identifiant unique</span>
|
||
|
<span class="Comment"><span class="Comment">#</span> (vous devez vérifier que l'identifier est VRAIMENT unique)</span>
|
||
|
<span class="Comment"><span class="Comment">#</span> attention l'identifiant unique ne doit pas </span>
|
||
|
<span class="Comment"><span class="Comment">#</span> contenir le caractère choisi.</span>
|
||
|
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>X</span><span class="StringRegexp"><span class="StringRegexp">/</span>_was_x_<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
|
||
|
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>Y</span><span class="StringRegexp"><span class="StringRegexp">/</span>_was_y_<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
|
||
|
|
||
|
<span class="Comment"><span class="Comment">#</span> transforme la longue chaine de caractère</span>
|
||
|
<span class="Comment"><span class="Comment">#</span> en un seul caractère</span>
|
||
|
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span><li></span><span class="StringRegexp"><span class="StringRegexp">/</span>X<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
|
||
|
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span><<span class="StringRegexpSpecial">\/</span>li></span><span class="StringRegexp"><span class="StringRegexp">/</span>Y<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
|
||
|
|
||
|
<span class="Comment"><span class="Comment">#</span> Utilisation de la première méthode</span>
|
||
|
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>X([^X]*)Y</span><span class="StringRegexp"><span class="StringRegexp">/</span><span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
|
||
|
|
||
|
<span class="Comment"><span class="Comment">#</span> Retransformation des lettres en chaines</span>
|
||
|
<span class="Comment"><span class="Comment">#</span> de caractères</span>
|
||
|
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>X</span><span class="StringRegexp"><span class="StringRegexp">/</span><li><span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
|
||
|
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>Y</span><span class="StringRegexp"><span class="StringRegexp">/</span><<span class="StringRegexpSpecial">\/</span>li><span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
|
||
|
|
||
|
<span class="Comment"><span class="Comment">#</span> retour des anciens caractères.</span>
|
||
|
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>_was_x_</span><span class="StringRegexp"><span class="StringRegexp">/</span>X<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
|
||
|
<span class="StringRegexp"><span class="StringRegexp"><span class="SupportFunction">s</span>/</span>_was_y_</span><span class="StringRegexp"><span class="StringRegexp">/</span>Y<span class="StringRegexp">/</span></span><span class="StringRegexp"><span class="StringRegexp"><span class="Keyword">g</span></span></span>
|
||
|
</pre></div>
|
||
|
|
||
|
<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 qu’il 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 j’ai utilisé une syntaxe HTML dans mon exemple. Mais dans l’utilisation réelle que j’en 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="choixrss">
|
||
|
<a id="rss" href="http://feeds.feedburner.com/yannespositocomfr">
|
||
|
s'abonner
|
||
|
</a>
|
||
|
</div>
|
||
|
<script type="text/javascript">
|
||
|
$(document).ready(function(){
|
||
|
$('#comment').hide();
|
||
|
$('#clickcomment').click(showComments);
|
||
|
});
|
||
|
function showComments() {
|
||
|
$('#comment').show();
|
||
|
$('#clickcomment').fadeOut();
|
||
|
}
|
||
|
document.write('<div id="clickcomment">Commentaires</div>');
|
||
|
</script>
|
||
|
<div class="flush"></div>
|
||
|
<div class="corps" id="comment">
|
||
|
<h2 class="first">commentaires</h2>
|
||
|
<noscript>
|
||
|
|
||
|
</noscript>
|
||
|
|
||
|
<script type="text/javascript">
|
||
|
var idcomments_acct = 'a307f0044511ff1b5cfca573fc0a52e7';
|
||
|
var idcomments_post_id = '/Scratch/fr/blog/2010-02-16-All-but-something-regexp--2-/';
|
||
|
var idcomments_post_url = 'http://yannesposito.com/Scratch/fr/blog/2010-02-16-All-but-something-regexp--2-/';
|
||
|
</script>
|
||
|
<span id="IDCommentsPostTitle" style="display:none"></span>
|
||
|
<script type='text/javascript' src='/Scratch/js/genericCommentWrapperV2.js'></script>
|
||
|
|
||
|
</div>
|
||
|
|
||
|
<div id="entete" class="corps_spaced">
|
||
|
<div id="liens">
|
||
|
<ul><li><a href="/Scratch/fr/">Acceuil</a></li>
|
||
|
<li><a href="/Scratch/fr/blog/">Blog</a></li>
|
||
|
<li><a href="/Scratch/fr/about/">À propos</a></li>
|
||
|
<li><a href="/Scratch/fr/contact/">Contact</a></li></ul>
|
||
|
</div>
|
||
|
<div class="flush"></div>
|
||
|
<hr/>
|
||
|
<div id="next_before_articles">
|
||
|
<div id="previous_articles">
|
||
|
articles précédents
|
||
|
|
||
|
<div class="previous_article">
|
||
|
<a href="/Scratch/fr/blog/2010-02-15-All-but-something-regexp/">← Expression régulière pour tout sauf quelquechose</a>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
<div class="previous_article">
|
||
|
<a href="/Scratch/fr/blog/2010-01-12-antialias-font-in-Firefox-under-Ubuntu/">← Fontes adoucies sous Ubuntu Firefox</a>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
<div class="previous_article">
|
||
|
<a href="/Scratch/fr/blog/2010-01-04-Change-default-shell-on-Mac-OS-X/">← Changer le shell par défaut sous Mac OS X</a>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
</div>
|
||
|
<div id="next_articles">
|
||
|
articles suivants
|
||
|
|
||
|
<div class="next_article">
|
||
|
<a href="/Scratch/fr/blog/2010-02-18-split-a-file-by-keyword/">découper un fichier par mots clés→ </a>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
<div class="next_article">
|
||
|
<a href="/Scratch/fr/blog/2010-02-23-When-regexp-is-not-the-best-solution/">Quand se passer des expressions régulières ?→ </a>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
<div class="next_article">
|
||
|
<a href="/Scratch/fr/blog/2010-03-22-Git-Tips/">Astuces Git→ </a>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
</div>
|
||
|
<div class="flush"></div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
<div id="bottom">
|
||
|
<div>
|
||
|
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/deed.fr">Droits de reproduction ©, Yann Esposito</a>
|
||
|
</div>
|
||
|
<div id="lastmod">
|
||
|
Écrit le : 16/02/2010 <br/>
|
||
|
dernière modification : 15/07/2010
|
||
|
</div>
|
||
|
<div>
|
||
|
Site entièrement réalisé avec
|
||
|
<a href="http://www.vim.org">Vim</a>
|
||
|
et
|
||
|
<a href="http://nanoc.stoneship.org">nanoc</a>
|
||
|
</div>
|
||
|
<div>
|
||
|
<a href="/Scratch/fr/validation/">Validation</a>
|
||
|
<a href="http://validator.w3.org/check?uri=referer"> [xhtml] </a>
|
||
|
.
|
||
|
<a href="http://jigsaw.w3.org/css-validator/check/referer?profile=css3"> [css] </a>
|
||
|
.
|
||
|
<a href="http://validator.w3.org/feed/check.cgi?url=http%3A//yannesposito.com/Scratch/fr/blog/feed/feed.xml">[rss]</a>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="clear"></div>
|
||
|
</div>
|
||
|
</body>
|
||
|
</html>
|