2009-01-03 8 views
1

Je suis coincé sur un problème de RegEx qui est apparemment très simple et pourtant je n'arrive pas à le faire fonctionner.Regex pour capturer un groupe optionnel au milieu d'un bloc d'entrée

Supposons que j'ai entrée comme ceci:

Some text %interestingbit% lots of random text lots and lots more %anotherinterestingbit% 
Some text %interestingbit% lots of random text OPTIONAL_THING lots and lots more %anotherinterestingbit% 
Some text %interestingbit% lots of random text lots and lots more %anotherinterestingbit% 

Il y a beaucoup de blocs répétitifs dans l'entrée et dans chaque bloc, je veux saisir certaines choses qui sont toujours là (% interestingbit% et% anotherinterestingbit%), mais il y a aussi un peu de texte qui peut ou ne peut pas se produire entre-eux (OPTIONAL_THING) et je veux le capturer s'il est là.

Un RegEx comme celui-ci correspond uniquement à des blocs avec OPTIONAL_THING dans (et les travaux de capture nommés):

%interestingbit%.+?((?<OptionalCapture>OPTIONAL_THING)).+?%anotherinterestingbit% 

Il semble donc que c'est juste une question de faire l'ensemble du groupe en option, non? Voilà ce que j'ai essayé:

%interestingbit%.+?((?<OptionalCapture>OPTIONAL_THING))?.+?%anotherinterestingbit% 

Mais je trouve que même si cela correspond à tous les 3 blocs de la capture du nom (de OptionalCapture) est vide dans tous! Comment puis-je faire fonctionner ça?

Notez qu'il peut y avoir beaucoup de texte dans chaque bloc, y compris les retours à la ligne, c'est pourquoi j'ai mis ". +?" plutôt que quelque chose de plus spécifique. J'utilise des expressions régulières .NET, testant avec The Regulator.

Répondre

2

Mes pensées vont dans le même sens que l'idée de Niko. Cependant, je suggère de placer le 2ème. +?à l'intérieur du groupe facultatif au lieu du premier, comme suit:

%interestingbit%.+?(?:(?<optionalCapture>OPTIONAL_THING).+?)?%anotherinterestingbit% 

Ceci évite le retour en arrière inutile. Si le premier. +? est à l'intérieur du groupe facultatif et OPTIONAL_THING n'existe pas dans la chaîne de recherche, l'expression régulière ne le saura pas jusqu'à ce qu'il arrive à la fin de la chaîne. Il faudra ensuite revenir en arrière, peut-être un peu, pour faire correspondre% un autre intérêt%, ce qui, comme vous l'avez dit, existera toujours. De même, puisque OPTIONAL_THING, quand il existe, sera toujours avant% elseinterestingbit%, alors le texte après il est effectivement optionnel et s'intègre plus naturellement dans le groupe optionnel.

+0

Ta-ta-da-da! Ça marche! Merci beaucoup. – EMP

0

Pourquoi avez-vous l'ensemble supplémentaire de parenthèses?

Essayez ceci:

%interestingbit%.+?(?<OptionalCapture>OPTIONAL_THING)?.+?%anotherinterestingbit% 

Ou peut-être que cela fonctionne:

%interestingbit%.+?(?<OptionalCapture>OPTIONAL_THING|).+?%anotherinterestingbit% 

Dans cet exemple, le groupe capture OPTIONAL_THING, ou rien.

+0

Non, désolé, aucun de ces travaux. Ils sont les mêmes que mon regex avec le groupe étant facultatif - tous les 3 blocs correspondent, mais sans OPTIONAL_THING étant capturé. – EMP

+0

@Evgeny, Êtes-vous sûr. +? est en train de rendre le wildcard "ungreedy?" Peut-être que vous pouvez essayer. *? au lieu. – strager

+0

@strager, essayé, ne fait pas de différence – EMP

0

Essayez ceci:

%interestingbit%(?:(.+)(?<optionalCapture>OPTIONAL_THING))?(.+?)%anotherinterestingbit% 

Il y a d'abord un groupe non-capture qui correspond .+OPTIONAL_THING ou rien. Si une correspondance est trouvée, il y a le groupe nommé à l'intérieur, qui capture OPTIONAL_THING pour vous. Le reste est capturé avec .+?%anotherinterestingbit%.

[modifier]: J'ai ajouté quelques parenthèses pour les groupes de capture supplémentaires, maintenant les groupes capturés correspondent aux suivants:

  • 1 $: texte avant OPTIONAL_THING ou rien
  • 2 $ ou optionalCapture $: OPTIONAL_THING ou rien
  • $ 3: texte après OPTIONAL_THING, ou si OPTIONAL_THING ne se trouve pas, le texte intégral entre% interestingbit% et% anotherinterestingbit%

Ar e ces trois matches que vous cherchez?

+0

Désolé, mais cela a le même problème que l'utilisation d'un grand "|" - le premier match comprend deux blocs, donc il n'y a que 2 correspondances au total, et non 3. – EMP

+0

Oooops .. édité ma réponse avant de remarquer qu'il y avait une nouvelle réponse AU-DESSUS de ma réponse. Une autre chose a appris à propos de Stack Overflow - les réponses ne sont pas dans l'ordre chronologique ... –

Questions connexes