2009-11-14 4 views
2

J'essaie d'extraire tous les liens qui contiennent/thumb/dans les "". En fait, j'ai seulement besoin d'utiliser les images src. Je ne sais pas si les images se termineront avec jpg ou s'il y aura des problèmes de sensibilité à la casse, etc. Je me soucie vraiment du lien complet.Pourquoi cette regex est-elle gourmande?

m = Regex.Match(page, @"""(.+?/thumbs/.+?)"""); 
//... 
var thumbUrl = m.Groups[1].Value; 

Mon code complet

var page = DownloadWebPage(url); 
    var reg = new Regex(@"Elements\s+\((.*)\)", RegexOptions.Multiline); 
    var m = reg.Match(page); 
    var szEleCount= m.Groups[1].Value; 
    int eleCount = int.Parse(szEleCount); 

    m = Regex.Match(page, @"""(.+?/thumbs/.+?)"""); 
    while (m.Success) 
    { 
     var thumbUrl = m.Groups[1].Value; 
     //i break here to see a problem 
     m = m.NextMatch(); 
    } 

thumbUrl ressemble

centre \ "> ... beaucoup de texte, pas/pouces/... src = \" http://images.fdhkdhfkd.com/thumbs/dfljdkl/22350.jpg

+0

Pour votre information, l'option 'Multiline' ISN » t faire quelque chose pour vous. Si vous voulez que le point corresponde aux séparateurs de ligne, vous devez utiliser 'Singleline' à la place. –

Répondre

3

La façon dont un réticente (non gourmand) quantificateurs fonctionne est, une fois qu'il commence à correspondre, il arrête au premier opportunité. Ce que vous essayez de faire est de faire correspondre la quantité minimale de texte qui répond à vos critères, ce qui n'est pas la même chose; vous devez toujours vous assurer qu'il ne commence pas correspondant avant que vous le vouliez. Comme d'autres l'ont suggéré, vous pouvez le faire en remplaçant le .+? dans votre expression régulière par quelque chose qui ne correspond pas à des guillemets, comme [^""]+.

Mais cela vous laisse toujours avec un problème de performance. Dans votre exemple, l'expression régulière commence à correspondre lorsqu'elle voit la citation dans center">; quand il atteint la citation à src=" (en supposant que vous avez changé le .+? en [^""]+), il annulera cette tentative de rapprochement. La tentative suivante, commençant à la citation dans src=" réussira. Donc, vous obtenez le bon résultat maintenant, mais vous perdez encore beaucoup de temps sur cette première tentative de match ratée.

La clé pour écrire des expressions rationnelles rapides est de s'assurer que, si une tentative de correspondance échoue, elle échoue aussi rapidement que possible. Par exemple, je pense qu'il est prudent de supposer que vous ne voulez pas de crochets entre les " et /thumbs/, alors ajoutez-les à l'ensemble de caractères que vous ne voulez pas faire correspondre: [^""<>]+. Maintenant, toute tentative de match commençant à la citation center"> sera annulée à la prochaine position.

Il y a d'autres choses que vous pouvez faire pour optimiser l'expression régulière, impliquant des groupes atomiques et lookaheads négatives, mais ce sera probablement aussi vite que vous avez besoin:

@"""([^""<>]+/thumbs/[^""<>]+)""" 
1

Le problème est que. +? consomme également « s, il continue à correspondre à l'extérieur de l'attribut src Utilisez ceci:..

m = Regex.Match(page, @"""([^""]+/thumbs/[^""]+)"""); 
+0

J'ai été tenté de marquer le vôtre comme correct. –

+0

donc très tenté ... –

4

expressions régulières nongreedy peuvent être lents parce que le moteur doit faire beaucoup de retours en arrière

Celui-ci Seules les utilisations des expressions gourmandes:

@"""([^""]*/thumbs/[^""]*)""" 

au lieu de chercher le moins de quoi que ce soit, il correspond à autant de non-guillemets doubles car il peut

0

Habituellement, lorsque vous avez une expression régulière que vous utilisez un champ statique et spécifiez RegexOptions.Compiled Option:

static Regex template = new Regex(@"""(.+?/thumbs/.+?)""", RegexOptions.Compiled | RegexOptions.Multiline) 
+0

Un certain nombre d'objets Regex sont automatiquement mis en cache, donc en stocker un dans un champ n'aura pas nécessairement d'effet sur les performances. De plus, les expressions régulières 'Compiled' peuvent être plus rapides, mais elles sont beaucoup plus chères à créer; Si vous devez utiliser cette option dépend de la façon dont vous utilisez l'expression régulière. http://blogs.msdn.com/bclteam/archive/2004/11/12/256783.aspx –

Questions connexes