----- isHidden: false menupriority: 1 kind: article created_at: 2010-02-16T10:33:21+02:00 title: Tout sauf quelquechose en expression régulière. tags: - regexp - regular expression ----- Dans mon [précédent article](previouspost) 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 :
a.....a......b..b..a....a....b...Voici les deux erreurs communes et une solution :
/a.*b/
a.....a......b..b..a....a....b...
La première erreur vient de l'utilisation du *terrible* `.*`. Parce que vous allez matcher la chaîne de caractère la plus longue possible.
/a.*?b/ a.....a......b..b..a....a....b...L'autre manière naturelle de répondre à ce problème est de changer la *greediness*. Mais ce n'est pas assez parce que vous allez matcher du premier `a` au premier `b` après celui-ci. On peut alors constater que votre chaine de caractère ne devrait comprendre ni la lettre `a` ni la lettre `b`. Ce qui emène à la dernière solution élégante.
/a[^ab]*b/ a.....a......b..b..a....a....b...Jusqu'ici, c'était facile. Maintenant comment fait vous quand au lieu de `a` vous avez une chaine de caractère ? Par exemple, vous voulez matcher:
...
[anything not containing ]
([^<]|<[^l]|])*
...
([^<]|<[^l]|])*(|<|
# 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//X/g
s/<\/li>/Y/g
# Utilisation de la première méthode
s/X([^X]*)Y//g
# Retransformation des lettres en chaines
# de caractères
s/X/ /g
s/Y/<\/li>/g
# retour des anciens caractères.
s/_was_x_/X/g
s/_was_y_/Y/g