12
votes

Expressions régulières en C # fonctionnant lentement

J'ai fait un peu de travail avec regex au cours de la semaine dernière et a réussi à faire beaucoup de progrès, cependant, je suis toujours assez n00b. J'ai une regex écrit en C #: xxx pré>

Pour une raison quelconque, lorsque vous appelez l'expression régulière ISMETHODREGEX.Amatch (), il est suspendu pendant 30 secondes sur la chaîne suivante: P>

"\t * Returns collection of active STOP transactions (transaction type 30) "


9 commentaires

Avez-vous essayé de compiler la regex? L'une des surcharges du constructeur fournit cette capacité.


@Steve: Je viens de me tester et après la compilation, cela prend encore beaucoup de temps. Je peux reproduire longtemps sur ma propre machine à Linqpad.


Je sais que c'est à côté du point, mais votre regex a l'air très fragile pour moi. D'une manière ou d'une autre, je pense que la performance est le moindre de vos problèmes.


Hey Chris, comment allez-vous y écrire?


Que diriez-vous d'expliquer le problème réel que vous essayez de résoudre?


OK, ce problème particulier consiste à numériser un fichier de code (différentes langues différentes, C # Java et VB) et à rechercher les appels de méthode, les noms de classe et l'espace de noms. J'ai cherché certains analyseurs de code mais je n'ai rien trouvé récent (qui gère des produits comme des génériques), j'ai donc décidé d'écrire la mienne. Cette regex est celle pour trouver des appels de méthode en C #, ils semblent tous bien fonctionner, mais comme je l'ai déjà testé, je constate que la méthode regex n'est pas très rapide, pensées?


Il est également valable pour indiquer statique privé au lieu de statique privé . Je suis sûr qu'il y a d'autres problèmes. Le problème avec l'utilisation d'une expression de ce "complet" est qu'il fait un gâchis non négligeable, est fréquemment faux et il n'est pas pratique d'incarner en cela les règles d'une spécification linguistique. La validation simplement de la validation d'une adresse électronique avec REGEX utilise considérablement un motif plus long que ce que vous avez. J'aurais une attention particulière à @chaospandion, parce que je soupçonne qu'il a raison.


Jetez un coup d'œil à ceci ( ex-parrot.com/~pdw/mail- Rfc822-address.html ) pour sh * ts et rigole ...


Cela pourrait donner une idée de savoir ce qu'il faut rechercher: régulier-expressions.info/catattrophique.html < / a>


3 Réponses :


3
votes

edit strong>: Je pense que la question de la performance est de la manière dont code> Le groupe correspondant est effectué. Je me suis réarrangé pour correspondre à un premier paramètre, puis n'importe quel nombre de paramètres successifs, ou éventuellement aucun du tout. J'ai aussi j'ai changé le type \ s * code> entre le type de paramètre et le nom sur \ s + code> (je pense que cela était responsable de beaucoup de backtracking car il ne permet aucun espaces, de sorte que objet code> pourrait correspondre comme obj code> et ect code> avec \ s * code> correspondant pas d'espaces) et il semble fonctionner beaucoup plus vite : XXX PRE>


EDIT STRY>: Comme dûment signalé par @Dan, ce qui suit est simplement parce que la regex peut quitter tôt. P>

C'est en effet une situation vraiment bizarre, mais si je retiens les deux correspondances facultatives au début (pour le public / privé / interne / protégé et statique / virtuel / abstrait), il commence à être à nouveau exécuté presque instantanément: P>

string isMethodRegex = 
    @"\b(public|private|internal|protected)\s*(static|virtual|abstract)"+
    @"(?<returnType>[a-zA-Z\<\>_1-9]*)\s(?<method>[a-zA-Z\<\>_1-9]+)\s*\"+
    @"((?<parameters>(([a-zA-Z\[\]\<\>_1-9]*\s*[a-zA-Z_1-9]*\s*)[,]?\s*)+)\)";
var IsMethodRegex = new Regex(isMethodRegex);

string s = "\t * Returns collection of active STOP transactions (transaction type 30) ";

Console.WriteLine(IsMethodRegex.IsMatch(s));


2 commentaires

Le résultat de ceci est un «faux», correct? Il peut exclure le match immédiatement parce qu'il ne commence pas par «P» ou «I», donc c'est une recherche triviale.


@Dan: En effet, vous êtes correct. Je soupçonne que cela a quelque chose à voir avec la manière dont la partie est effectuée.




1
votes

Avez-vous essayé de compiler votre regex?

string pattern = @"\b[at]\w+";
RegexOptions options = RegexOptions.IgnoreCase | RegexOptions.Compiled;
string text = "The threaded application ate up the thread pool as it executed.";
MatchCollection matches;

Regex optionRegex = new Regex(pattern, options);
Console.WriteLine("Parsing '{0}' with options {1}:", text, options.ToString());
// Get matches of pattern in text
matches = optionRegex.Matches(text);
// Iterate matches
for (int ctr = 1; ctr <= matches.Count; ctr++)
   Console.WriteLine("{0}. {1}", ctr, matches[ctr-1].Value);


1 commentaires

Nous avons déjà essayé, cela n'a fait aucune différence. En fait, il y avait une réponse qui a dit que la même chose il y a quelque temps que l'auteur a supprimé.