scratch/output/Scratch/fr/blog/2010-02-16-All-but-something-regexp--2-/index.html
Yann Esposito (Yogsototh) f19c2a270a Regen
2012-01-20 14:41:44 +01:00

267 lines
No EOL
16 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.

<?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>
<!--[if lt IE 9]>
<script src="http://ie7-js.googlecode.com/svn/version/2.1(beta4)/IE9.js"></script>
<![endif]-->
<title>Tout sauf quelquechose en expression régulière.</title>
</head>
<body lang="fr" class="article">
<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">&darr; Menu &darr;</a></div>
<div id="choixlang">
<a href="/Scratch/en/blog/2010-02-16-All-but-something-regexp--2-/" onclick="setLanguage('en')">in English</a>
</div>
<div class="flush"></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> 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.....<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&nbsp;:</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 lutilisation 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>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 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>Jusquici, cétait facile. Maintenant comment fait vous quand au lieu de <code>a</code> vous avez une chaine de caractère&nbsp;?</p>
<p>Par exemple, vous voulez matcher:</p>
<div><pre class="twilight">
&lt;li&gt;...&lt;li&gt;
</pre></div>
<p>Cest un peu difficile. Vous devez matcher</p>
<div><pre class="twilight">
&lt;li&gt;[anything not containing &lt;li&gt;]&lt;/li&gt;
</pre></div>
<p>La première méthode serait dutiliser le même rainsonnement que dans mon <a href="previouspost">article précédent</a>. Ici un premier essai&nbsp;:</p>
<div><pre class="twilight">
&lt;li&gt;([^&lt;]|&lt;[^l]|&lt;l[^i]|&lt;li[^&gt;])*&lt;/li&gt;
</pre></div>
<p>Mais il y a encore une erreur. Pensez à la chaine de caractère suivante&nbsp;:</p>
<div><pre class="twilight">
&lt;li&gt;...&lt;li&lt;/li&gt;
</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><pre class="twilight">
&lt;li&gt;([^&lt;]|&lt;[^l]|&lt;l[^i]|&lt;li[^&gt;])*(|&lt;|&lt;l|&lt;li)&lt;/li&gt;
</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>&nbsp;?</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>
<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>&lt;li&gt;</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>&lt;<span class="StringRegexpSpecial">\/</span>li&gt;</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>&lt;li&gt;<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>&lt;<span class="StringRegexpSpecial">\/</span>li&gt;<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 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="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>
Vous devez activer javascript pour commenter.
</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/">Bienvenue</a></li>
<li><a href="/Scratch/fr/blog/">Blog</a></li>
<li><a href="/Scratch/fr/softwares/">Softwares</a></li>
<li><a href="/Scratch/fr/about/">À propos</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/"><span class="nicer">«</span>&nbsp;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/"><span class="nicer">«</span>&nbsp;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/"><span class="nicer">«</span>&nbsp;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&nbsp;<span class="nicer">»</span></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 ?&nbsp;<span class="nicer">»</span></a>
</div>
<div class="next_article">
<a href="/Scratch/fr/blog/2010-03-22-Git-Tips/">Astuces Git&nbsp;<span class="nicer">»</span></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
modifié le : 20/04/2011
</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>