2010-11-05 7 views
3

Je suis en train le code suivant sur Java:Quel est le problème avec cette regex?

String test = "http://asda.aasd.sd.google.com/asdasdawrqwfqwfqwfqwf"; 
String regex = "[http://]{0,1}([a-zA-Z]*.)*\\.google\\.com/[-a-zA-Z/_.?&=]*"; 
System.out.println(test.matches(regex)); 

Il fonctionne pendant plusieurs minutes (après que je tuais la machine virtuelle) sans résultat. Quelqu'un peut-il m'aider?

BTW: Que me recommanderez-vous de faire pour accélérer les regex weblink-testng à l'avenir?

Répondre

7

[http://] est une classe de caractères, ce qui signifie tout un de ces personnages du jeu. Il suffit de laisser ces crochets si doit commencer par http://. Si c'est facultatif, vous pouvez utiliser (http://)?.

Un problème évident est que vous cherchez la séquence ([a-zA-Z]+.)*\\.google - cela va faire beaucoup de retours en arrière en raison de cette . nue qui signifie « tout caractère » plutôt que la période littérale que vous vouliez.

Mais même si vous le remplacer par ce que vous signifiait, ([a-zA-Z]+\\.)*\\.google, vous avez encore un problème - ce sera alors besoin de deux . caractères immédiatement avant google. Vous devriez plutôt essayer:

String regex = "(http://)?([a-zA-Z]+\\.)*google\\.com/[-a-zA-Z/_.?&=]*"; 

qui retourne immédiatement pour moi avec un match true. Gardez à l'esprit que cela nécessite actuellement le / à la fin de google.com. Si c'est un problème, c'est un correctif mineur, mais je l'ai laissé là puisque vous l'aviez dans votre regex d'origine.

+0

vous pouvez utiliser (i?) [A-z] au lieu de [a-zA-Z], il ignore le cas – ant

4

Vous essayez de faire correspondre le schéma en tant que classe de caractères entre crochets. Cela signifie seulement zéro ou l'un des caractères de cet ensemble. Vous voulez un sous-masque, avec des parenthèses. Vous pouvez également changer {0,1} pour simplement dire ?.

De même, vous devez supprimer la période juste avant google\\.com car vous recherchez déjà une période dans le sous-modèle de sous-domaine de votre expression régulière. Comme le fait remarquer Cherouvim, vous avez également oublié d'échapper à cette période.

String regex = "(http://)?([a-zA-Z]+\\.)*google\\.com/[-a-zA-Z/_.?&=]*"; 
+0

Même si cette modification n'empêche pas Java de passer trop longtemps à l'expression régulière. –

+0

Mettez un '+' après le premier '*'. – tchrist

3

Dans la partie ([a-zA-Z]*.), vous devez soit échapper le . (parce que maintenant il signifie "tous les caractères") ou le supprimer.

+0

Strike! C'est l'erreur qui a provoqué le comportement de "boucle infinie". bonne prise! (vérifié votre solution avec ideone) –

1

En supposant que vous fixer le ([a-zA-Z]*\\.) vous devez changer *-+ de sorte que la partie devient ([a-zA-Z]+\\.). Sinon, vous acceptez le http://...google.com et ceci n'est pas valide.

2

L'expression régulière présente deux problèmes.

Le premier est facile, comme cela a été mentionné par d'autres. Vous devez faire correspondre "http: //" en tant que sous-masque, pas en tant que classe de caractères. Changez les parenthèses en parenthèses.

Le deuxième problème entraîne de très mauvaises performances.Il fait reculer l'expression régulière, essayant de faire correspondre le modèle.

Ce que vous essayez de faire est de faire correspondre zéro ou plusieurs sous-domaines, qui sont des groupes de lettres suivis d'un point. Puisque vous voulez faire correspondre le point explicitement, échapper le point. Supprimez également le point devant "google" afin de pouvoir faire correspondre "http://google.com/etc" (c'est-à-dire, aucun point devant Google).

Ainsi, votre expression devient:

String regex = "(http://){0,1}([a-zA-Z]+\\.)*google\\.com/[-a-zA-Z/_.?&=]*"; 

L'exécution de cette regex sur votre exemple prend une fraction de seconde.

1

En regroupant une partie avant google.com, je suppose que vous recherchez une partie du nom d'hôte de l'URL. Je pense que rexep est un outil puissant, mais vous pouvez simplement utiliser URL Java class. Il y a la méthode getHost(). Ensuite, vous pouvez vérifier si le nom d'hôte se termine par google.com et le diviser ou utiliser une expression rationnelle plus simple avec uniquement le nom d'hôte.

URL url = new URL("http://asda.aasd.sd.google.com/asdasdawrqwfqwfqwfqwf"); 
String host = url.getHost(); 
if (host.endsWith("google.com")) 
    { 
    String [] parts = host.split("\\."); 
    for (String s: parts) 
     System.out.println(s); 
    } 
+0

Cela dépend de la connectivité réseau et des exigences de performance. – cherouvim

+0

Je l'ai testé sans connectivité réseau HTTP directe (proxy avec mot de passe), cette URL ne fonctionne pas dans le navigateur, mais j'ai été en mesure d'utiliser la classe URL. Pouvez-vous me donner plus d'informations sur la classe d'URL en fonction de la connectivité réseau? –

+0

J'ai testé la perfomance avec regex (http: //)? ([A-zA-Z0-9] + \\.) * Google ((syndication) | (-analytics))? \\. Com /[-a-zA-Z0-9/_.?&=]* et modèles google.com google-analytics.com googlesyndication.com Il faut 985 ms pour regex pour vérifier 100 000 liens , tandis que l'URL prend 156 ms –

Questions connexes