Expression régulière : souci

Bonjour!
Je voudrais récupérer tout le texte compris entre deux chaînes.
Cependant, avec ma méthode, je récupère aussi ces deux chaines, chose que je ne veux pas.

Exemple :

J’ai une chaine de ce type :

Que je récupère avec l’expression suivante :

Mais je ne voudrais pas avoir et

J’ai vraiment un souci avec ces regexp…

Capture avec des parenthèses :

(.*)

Bon après faut pas récupérer le résultat complet mais seulement la capture, la manière exacte de le faire va dépendre du langage que tu utilises.

C’est avec python…
Merci à toi!

Tu peux aussi utiliser :

(la chaine “http://” suivie de toute chaine ne contenant pas “<”)

Ça colle avec ton exemple, mais selon ce que tu parses, c’est peut-être moins pertinent.

suivant ton exemple, ça ça devrait marcher :

Non?

[code]import re

chaine=‘sdlfkm sdkljflhttp://coucou.com/fdlksj?kdsjkl=dsf&a=eslmskdlm’
expr = re.compile(r’(.*)’)
print expr.search(chaine).groups()[0]

Affiche http://coucou.com/fdlksj?kdsjkl=dsf&a=e[/code]

C’est du python 2.6, je n’ai pas plus récent sur ma machine, mais d’après la doc de python 3 je ne crois pas que l’API aie changée (docs.python.org/py3k/library/re.html).

Note que la compilation de l’expression n’est pas nécessaire mais améliore les performances. Il est aussi utile de savoir que tu peux prendre toute une page HTML, tout mettre dans une string et faire une fois la recherche et avoir tout les résultats dans une liste (ça peut être pratique).

L’exemple de kna, n’a pas le même sens. Il ne s’agit alors pas de chercher tout ce qui se trouve entre les balise , mais toutes les urls. Elle devrait d’ailleurs être complétée au moins comme ça je pense :

Au sujet de cette expression :

[ul]
[li][] : définit des classes de caractères donc [abc] va permettre de matcher a, b ou c[/li]
[li]^ : au début d’une définition de classe de caractère il inverse celle-ci donc [^abc] va matcher n’importe quoi sauf a, b et c[/li]
[li][^] : va donc matcher tout caractère sauf <, l, i, n ou k[/li]
[li]+ : indique que la classe précédente peut se trouver 1 ou plusieurs fois dans ce que l’on matche [^]+ peut matcher ‘abc’, ‘u’, ‘-’, ‘utr_hsd’, …[/li]
[li][$] : est une classe de caractère qui matche n’importe quel des caractères ‘$’, ‘<’, ‘>’, ‘l’, ‘i’, ‘n’ et ‘k’[/li][/ul]

L’expression de kna correspond à :

toute chaines qui commence par ‘http://’ suivi d’au moins un caractère qui n’est pas ‘<’.

Celle de syam, c’est tout ce qui commence par ‘’, suivi de n’importe quoi, suivi de ‘’.

Autre remarque, si on prend ce texte d’origine :

Alors l’expression régulière (.*) te renverra la chaîne abcdefghi (sauf si tu as donné des options spécifiques à ton moteur de regex).
En effet, le symbole * est dit “greedy” c’est à dire qu’il va essayer de faire correspondre le maximum qu’il peut.

Pour éviter ça, soit tu utilises un opérateur “lazy” qui va s’écrire (.*?) ou, mieux quand c’est possible, une classe de caractères inversée dont parlait MisterFreez : ([^<]*)

Dans ce dernier cas ça veut dire :

  • la chaîne recherchée doit commencer par
  • ensuite on capture tous les caractères tant qu’on ne rencontre pas un <
  • enfin, ça doit être suivi de

L’opérateur lazy *? est à éviter si possible car il est généralement moins performant qu’une classe de caractères inversées.

À ce sujet, voir : regular-expressions.info/repeat.html

En effet, de plus je ne sais pas si comment se comporte l’API python mais il peut être pratique d’utiliser l’opérateur + pour forcer la présence d’au moins un caractère (* permet le vide). Donc au final ça donnerait :

Ainsi tu es sur d’avoir quelque chose de non-vide.

Un grand merci pour vos explications complètes. Je ne devrais pas avoir le moindre souci pour parser un fichier de flux rss avec ça.

Je ne le compilerai pas, car ne l’utilise qu’une fois, donc ça ira comme ça.

Promis, dès que je suis en vacance je me met aux regexp :slightly_smiling:

Et pour récupérer quelque chose qui s’étale sur plusieurs lignes? Pour l’instant je fais ça à coup de split, mais ça manque d’élégance.

en gros, je veux récupérer tout ce qui est entre

et
.
Sans succès avec cette regexp :

re.findall(r'<div id="main">([^<]*)</div id="footer">',a où a est le texte.
Je crois avoir vu un truc MULTILINE dans la doc python, j’y retourne.