2017-03-22 3 views
1

J'ai une chaîne que je veux séparer en segments spécifiques mais je ne peux pas correspondre au segment correct de la chaîne à cause de deux occurrences du même modèle.Trouver des segments spécifiques en utilisant regex

Ma chaîne:

@if(text.text isempty){<customer_comment>@cc{txt_without_comments}[email protected]</customer_comment>}else{@if(text.answer=='no'){<customer_comment>@{text.text}</customer_comment>}else{<answer>@{text.text}</answer>}[email protected]}[email protected] 

je dois correspondre: @if (text.text isempty) {@ cc {} txt_without_comments cc @} else {....} endif @

et pas les points imbriqués dans l'autre bloc.

Voici mon regex incomplète:

(?<match>(?<open>@if\((?<statement>[^)]*)\)\s*{)(?<ifblock>(.+?)(?:}else{)(?<elseblock>.*))(?<-open>)}[email protected]) 

Cette regex est trop gourmand dans le groupe ifblock il censé arrêter au premier} else {motif.

Edit: Ceci est le résultat exact que je veux produire:

match: @if(text.text isempty){<customer_comment>@cc{txt_without_comments}[email protected]</customer_comment>}else{@if(text.answer=='no'){<customer_comment>@{text.text}</customer_comment>}else{<answer>@{text.text}</answer>}[email protected]}[email protected] 

statement: text.text isempty 

ifblock: <customer_comment>@cc{txt_without_comments}[email protected]</customer_comment> 

elseblock: @if(text.answer=='no'){<customer_comment>@{text.text}</customer_comment>}else{<answer>@{text.text}</answer>}[email protected] 
+0

Veuillez fournir le résultat exact. –

+1

Mon résultat recherché est publié à la question. –

Répondre

1

Vous n'utilisez pas balancing groups correctement. Les groupes d'équilibrage doivent être utilisés pour pousser certaines valeurs dans la pile à l'aide d'une capture et être retirés de la pile avec d'autres captures, puis un conditional construct est nécessaire pour vérifier si la pile du groupe est vide et, si ce n'est pas le cas retour en arrière.

Ainsi, si la regex est la seule façon pour vous de faire correspondre ces chaînes, utilisez ce qui suit:

(?s)(?<match>@if\((?<statement>[^)]*)\)\s*{\s*(?<ifblock>.*?)\s*}\s*else\s*{\s*(?<elseblock>@if\s*\((?:([email protected]\s*\(|\}\s*[email protected]).|(?<a>)@if\s*\(|(?<-a>)\}\s*[email protected])*(?(a)(?!)))\}\s*[email protected]) 

Voir la regex demo. Cependant, écrire un analyseur personnalisé pourrait s'avérer une meilleure approche ici.

détails Motif:

  • (?s) - mode ligne unique sur (. correspond à saut de ligne)
  • (?<match> - début du groupe externe "match"
  • @if\( - une séquence char littéral @if(
  • (?<statement>[^)]*) - Groupe "instruction" capturant 0+ caractères autres que )
  • \)\s*{\s* - ), 0+ espaces blancs, {, 0+
  • espaces blancs (?<ifblock>.*?) - Groupe "ifblock" qui capture tout 0+ caractères, aussi peu que possible jusqu'à la première ...
  • \s*}\s*else\s*{\s* - 0+ espaces blancs, }, 0+ espaces blancs, else, 0+ espaces blancs, {, 0+
  • espaces blancs (?<elseblock>@if\s*\((?:([email protected]\s*\(|\}\s*[email protected]).|(?<a>)@if\s*\(|(?<-a>)\}\s*[email protected])*(?(a)(?!))) - Groupe "elseblock" capture:
    • @if\s*\(-@if, 0+ espaces blancs, (
    • (?: - début du groupe d'alternance, qui se répète 0+ fois
    • )* - extrémité du groupe d'alternance
    • (?(a)(?!)) - vérification conditionnelle si la quantité équilibrée de if et endif sont mis en correspondance
  • \}\s*[email protected]-}, 0+ espaces blancs, [email protected]
  • ) - fin du groupe "match" externe.