2009-09-17 9 views
2

Je suis assez sûr que les expressions régulières sont la voie à suivre, mais ma tête me fait mal à chaque fois que j'essaie d'élaborer l'expression régulière spécifique.Comment trouver si une chaîne Java contient X ou Y et contient Z

Quelle expression régulière dois-je trouver si une chaîne Java (contient le texte "ERROR" ou le texte "WARNING") AND (contient le texte "parsing"), où toutes les correspondances sont insensibles à la casse?

EDIT: J'ai présenté un cas spécifique, mais mon problème est plus général. Il peut y avoir d'autres clauses, mais elles impliquent toutes de faire correspondre un mot spécifique, en ignorant le cas. Il peut y avoir 1, 2, 3 ou plusieurs clauses.

Répondre

17

Si vous n'êtes pas à l'aise avec les expressions régulières, n'essayez pas de les utiliser pour quelque chose comme ça. Il suffit de faire ceci:

string s = test_string.toLowerCase(); 
if (s.contains("parsing") && (s.contains("error") || s.contains("warning")) { 
    .... 

parce que quand vous revenez à votre code dans six mois, vous comprendrez ce un coup d'oeil.

Edit: Voici une expression régulière pour le faire:

(?i)(?=.*parsing)(.*(error|warning).*) 

mais il est plutôt inefficace. Pour les cas où vous avez une condition OU, une approche hybride où vous recherchez plusieurs expressions régulières simples et combinez les résultats par programmation avec Java est généralement la meilleure, à la fois en termes de lisibilité et d'efficacité.

+0

Richie, vous avez raison. Cependant, j'ai donné un cas spécifique pour rendre la question facile à comprendre, mais mon problème est plus général. –

+1

s.contains ("error") ou s.contains ("warning") devrait être s.contains ("error") || s.contains ("warning"), n'est-ce pas? –

0

essayer:

If((str.indexOf("WARNING") > -1 || str.indexOf("ERROR") > -1) && str.indexOf("parsin") > -1) 
0

expressions régulières ne sont pas nécessaires ici. Essayez ceci:

if((string1.toUpperCase().indexOf("ERROR",0) >= 0 || 
    string1.toUpperCase().indexOf("WARNING",0) >= 0) && 
    string1.toUpperCase().indexOf("PARSING",0) >= 0) 

Cela prend également en charge les critères insensibles à la casse

6

Si vous voulez vraiment utiliser des expressions régulières, vous pouvez utiliser le test avant positif opérateur:

(?i)(?=.*?(?:ERROR|WARNING))(?=.*?parsing).* 

Exemples:

Pattern p = Pattern.compile("(?=.*?(?:ERROR|WARNING))(?=.*?parsing).*", Pattern.CASE_INSENSITIVE); // you can also use (?i) at the beginning 
System.out.println(p.matcher("WARNING at line X doing parsing of Y").matches()); // true 
System.out.println(p.matcher("An error at line X doing parsing of Y").matches()); // true 
System.out.println(p.matcher("ERROR Hello parsing world").matches()); // true  
System.out.println(p.matcher("A problem at line X doing parsing of Y").matches()); // false 
+0

System.out.println ("matches =" + Pattern.matches ("(? =. *? (?: ERROR | AVERTISSEMENT)) (? =. *? Parsing)", "ERREUR Hello parsing world")); renvoie false ... quelque chose ne fonctionne pas. –

+0

Oui, le '. *' Manquait à la fin. J'ai modifié mon message. –

0

utilisez this applet pour expérimenter avec reg. ex. L'expression peut ressembler à ceci:

if (str.matches("(?i)^.*?(WARNING|ERROR).*?parsing.*$")) { 
... 

Mais comme indiqué dans les réponses ci-dessus, il vaut mieux ne pas utiliser reg. ex. ici.

+0

System.out.println (Pattern.compile ("(? I) ^. *? (AVERTISSEMENT | ERREUR). *? Parsing. * $"). Matcher ("analyse ERREUR Bonjour tout le monde"). Matches()); renvoie false ... –

0

Je pense que ce regexp fera l'affaire (mais il doit y avoir une meilleure façon de le faire):

(.*(ERROR|WARNING).*parsing)|(.*parsing.*(ERROR|WARNING)) 
0

Si vous avez un nombre variable de mots que vous voulez faire correspondre je ferais quelque chose comme ça:

String mystring = "Text I want to match"; 
String[] matchings = {"warning", "error", "parse", ....} 
int matches = 0; 
for (int i = 0; i < matchings.length(); i++) { 
    if (mystring.contains(matchings[i]) { 
    matches++; 
    } 
} 

if (matches == matchings.length) { 
    System.out.println("All Matches found"); 
} else { 
    System.out.println("Some word is not matching :("); 
} 

Note: Je n'ai pas compilé ce code, donc je pourrais contenir des fautes de frappe.

0

Avec plusieurs constantes .*, l'analyseur appellera des milliers de tentatives de "back off et retry".

N'utilisez jamais .* au début ou au milieu d'un motif RegEx.

Questions connexes