2010-09-30 6 views
1

J'ai un modèle String à partir duquel j'ai besoin d'obtenir la liste des blocs #elseif.Expression régulière- Aide requise

Mais il ne renvoie qu'une seule correspondance, c'est-à-dire le premier bloC#elseif et non le second. Je dois aussi obtenir le deuxième bloC#elseif. Pourriez-vous s'il vous plaît m'aider à faire cela? Veuillez trouver le modèle de chaîne ci-dessous.

String template = 
     "This is a sample document." 
      + "#abc (#processing)" 
      + "FIRST This text can be repeated many times until do while is called." 
      + "#abcif (v2)" 
      + "Some sample text after 1st ElseIf." 
      + "#abcif(v2)" 
      + "; 
+0

double possible de [Regex besoin d'aide.] (Http://stackoverflow.com/questions/3823362/regex-help-needed) – NullUserException

+0

Le post précédent était de revenir un seul match. J'ai besoin d'obtenir tous les autres blocs – Apps

+0

Je ne pense pas sérieusement regex est le bon type d'outil pour l'analyse comme ça. Créez une grammaire et utilisez ANTLR. –

Répondre

2

Ce code

Pattern regexp = Pattern.compile("#elseif\\b(.*?)(?=#(elseif|else|endif))"); 
Matcher matcher = regexp.matcher(template); 
while (matcher.find()) 
    System.out.println(matcher.group()); 

produira

#elseif ($variable2)Some sample text after 1st ElseIf. 
#elseif($variable2)This text can be repeated many times until do while is called. SECOND ELSEIF 
#elseif ($variable2)SECOND Some sample text after 1st ElseIf. 
#elseif($variable2)SECOND This text can be repeated many times until do while is called. SECOND ELSEIF 

Le secret réside dans le positive lookahead(?=#(elseif|else|endif)), donc #elseif, #else ou #endif seront appariés, mais les caractères ne sont pas consommés. De cette façon, ils pourraient être trouvés par l'itération suivante.

1
#elseif\b(?:(?!#else\b|#endif\b).)* 

va correspondre à tout de la première #elseif dans un bloc jusqu'à (mais non y compris) la #else ou #endif le plus proche.

Pattern regex = Pattern.compile("#elseif\\b(?:(?!#else\\b|#endif\\b).)*", Pattern.DOTALL); 
Matcher regexMatcher = regex.matcher(subjectString); 
while (regexMatcher.find()) { 
    // matched text: regexMatcher.group() 
    // match start: regexMatcher.start() 
    // match end: regexMatcher.end() 
} 

Si vous avez besoin alors d'extraire les simples '# blocs elseif` de ce match, utilisez

#elseif\b(?:(?!#elseif\b).)* 

sur les résultats du premier match de regex ci-dessus. En Java:

Pattern regex = Pattern.compile("#elseif\\b(?:(?!#elseif\\b).)*", Pattern.DOTALL); 

etc.

1

Le gros problème ici est que vous avez besoin #elseif(..) à la fois comme un début et de fin marqueur dans l'expression régulière. Le premier match est la sous-chaîne

#elseif ($variable2)Some sample text after 1st ElseIf.#elseif($variable2) 

puis il commence à chercher le prochain match après cette séquence. Il manquera donc la deuxième #elseif de la première expression #if, car la séquence #elseif($variable2) faisait déjà partie du précédent.

je vais essayer de diviser la chaîne sur le motif "\\#elseif\\s*\\((.*?)\\)":

String[] temp = template.split("\\#elseif\\s*\\((.*?)\\)"); 

Maintenant, toutes les entrées temporaires à partir de temp[1] ont un bloc #elseif à leur début. Une autre scission sur (?:#else|#endif) devrait vous donner des chaînes ne contenant que les textes simples:

for (String s:temp) 
    System.out.println(s.split("(?:#else|#endif)")[0]); 

(n'a pas été en mesure de tester la deuxième scission, si elle ne fonctionne pas, le traiter comme un avis sur la seule stratégie;))

1
private static final Pattern REGEX = Pattern.compile(
    "#elseif\\s*\\(([^()]*)\\)(.*?)(?=#elseif|#else|#endif)"); 

public static void main(String[] args) { 
    Matcher matcher = REGEX.matcher(template); 
    while (matcher.find()) { 
     System.out.println(matcher.group(2)); 
    } 
}