2016-12-13 3 views
-1

Supposons que je souhaite créer une expression rationnelle de grande taille avec des groupes de capture à l'exécution en fonction des décisions de l'utilisateur.Java regex - Déterminez quel groupe de capture a été comparé et comptez les occurrences

Exemple simple:

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class Test {  
    static boolean findTag, findWordA, findOtherWord, findWordX; 

    static final String TAG = "(<[^>]+>)"; 
    static final String WORD_A = "(wordA)"; 
    static final String OTHER_WORD = "(anotherword)"; 
    static final String WORD_X = "(wordX)"; 

    static int tagCount = 0; 
    static int wordACount = 0; 
    static int otherWordCount = 0; 
    static int wordXCount = 0; 

    public static void main(String[] args) { 
     // Boolean options that will be supplied by the user 
     // make them all true in this example 
     findTag = true; 
     findWordA = true; 
     findOtherWord = true; 
     findWordX = true; 

     String input = "<b>this is an <i>input</i> string that contains wordX, wordX, anotherword and wordA</b>"; 

     StringBuilder regex = new StringBuilder(); 

     if (findTag) 
      regex.append(TAG + "|"); 

     if (findWordA) 
      regex.append(WORD_A + "|"); 

     if (findOtherWord) 
      regex.append(OTHER_WORD + "|"); 

     if (findWordX) 
      regex.append(WORD_X + "|"); 

     if (regex.length() > 0) { 
      regex.setLength(regex.length() - 1); 
      Pattern pattern = Pattern.compile(regex.toString()); 

      System.out.println("\nWHOLE REGEX: " + regex.toString()); 
      System.out.println("\nINPUT STRING: " + input); 

      Matcher matcher = pattern.matcher(input); 

      while (matcher.find()) { 
       // only way I know of to find out which group was matched: 
       if (matcher.group(1) != null) tagCount++; 
       if (matcher.group(2) != null) wordACount++; 
       if (matcher.group(3) != null) otherWordCount++; 
       if (matcher.group(4) != null) wordXCount++; 
      } 

      System.out.println(); 
      System.out.println("Group1 matches: " + tagCount); 
      System.out.println("Group2 matches: " + wordACount); 
      System.out.println("Group3 matches: " + otherWordCount); 
      System.out.println("Group4 matches: " + wordXCount); 

     } else { 
      System.out.println("No regex to build."); 
     } 
    } 
} 

Le problème est que je ne peux compter les matchs de chaque groupe seulement quand je sais d'avance que regex/groupes auxquels l'utilisateur veut trouver.

Notez que la regex complète contiendra beaucoup plus de groupes de capture et qu'ils seront plus complexes.

Comment puis-je déterminer quel groupe de capture a été apparié afin que je puisse compter les occurrences de chaque groupe, sans savoir à l'avance quels groupes l'utilisateur veut trouver?

+0

peut-être une réponse évidente, mais vous réalisez que vous pouvez utiliser 'GroupCount()' pour déterminer le nombre de groupes? –

+1

Pas vraiment lié mais 'StringBuilder' est utilisé précisément pour éviter la concaténation de chaînes (qui crée des' StringBuilder's supplémentaires pour chaque expression de concaténation). Donc, au lieu de 'regex.append (TAG +" | ");' use 'regex.append (TAG) .append (" | ");'. – Pshemo

+0

@PatrickParker le nombre de groupes ne suffit pas, j'ai besoin de savoir quels groupes comptent. – AndroidX

Répondre

0

construire l'expression rationnelle utilisée named groups:

(?<tag>wordA)|(?<wordx>wordX)|(?<anotherword>anotherword) 
+0

Cela fonctionne .... par curiosité est-ce la seule façon que nous pouvons le faire? – AndroidX

+0

puisque ce n'est pas vraiment un "pattern" mais plutôt un simple test d'égalité, je ne sais pas si regex est même nécessaire ici. – sweaver2112

+0

J'utilise des modèles ... le code ci-dessus est juste destiné à être un exemple simple. – AndroidX