2009-09-28 6 views
2

J'ai été googler & essayant de moi-même mais ne peut pas tout à fait le faire ...Regex pour faire correspondre le texte entre les délimiteurs spécifiés? (Je ne peux pas le faire moi-même)

QUESTION: Quelle est l'expression régulière pourrait être utilisé pour sélectionner du texte ENTRE (mais sans inclure) le texte du délimiteur. Ainsi, à titre d'exemple:

Start Marker=ABC 
Stop Marker=XYZ 

---input--- 
This is the first line 
And ABCfirst matched hereXYZ 
and then 
again ABCsecond matchXYZ 
asdf 
------------ 

---expected matches----- 
[1] first matched here 
[2] second match 
------------------------ 

Merci

+2

Un petit commentaire pour ceux qui lisent ceci - si vous regardez cette question parce que vous voulez utiliser des expressions régulières pour l'analyse XML, ne le faites pas. C'est quelque chose que je vois souvent dans #bash, et c'est une très mauvaise idée - l'analyse XML est étonnamment difficile à obtenir, et toute tentative de capture des subtilités de la syntaxe dans une expression régulière est vouée à l'échec. Utilisez une bibliothèque ou un outil créé à cet effet - si, comme les gens qui demandent dans #bash, vous voulez quelque chose que vous pouvez utiliser à partir d'un script shell, voir XMLStarlet. –

Répondre

10

standard ou la syntaxe regex étendue ne peut pas le faire, mais ce qu'il peut faire est de créer des groupes de match que vous pouvez ensuite sélectionner. Par exemple:

ABC(.*)XYZ 

mémorisera quoi que ce soit entre ABC et XYZ comme \1 (autrement connu sous le nom du groupe 1). Si vous utilisez des PCRE (Perl-Regular Regular Expressions), les assertions lookahead et lookbehind sont également disponibles - mais les groupes sont la solution la plus portable et la plus performante. En outre, si vous utilisez des PCRE, vous devez utiliser *? pour vous assurer que la correspondance n'est pas gourmande et qu'elle se terminera à la première occasion.

Vous pouvez tester vous-même dans un interpréteur Python (la syntaxe regex Python est PCRE-dérivé):

>>> import re 
>>> input_str = ''' 
... This is the first line 
... And ABC first matched hereXYZ 
... and then 
... again ABCsecond matchXYZ 
... asdf 
... ''' 
>>> re.findall('ABC(.*?)XYZ', input_str) 
[' first matched here', 'second match'] 
+0

le groupe \ 1 contiendrait-il "premier apparié ici" et "deuxième match", ou tout entre le premier ABC jusqu'au dernier XYZ? – kender

+1

@kender - Pour avoir une seule correspondance, deux choses devraient être vraies: L'indicateur multiligne devrait être défini, et l'astérisque devrait être gourmand. Sinon, nous avons deux correspondances distinctes, chacune ayant ses propres groupes. –

+0

En fait, j'utilise C#, donc est-ce que l'idée que je pourrais avoir dans les groupes (par exemple le groupe \ 1) en C#? – Greg

3

/ABC(.*?)XYZ/

Par défaut, expression régulière sont gourmands. Le '?' après le . caractère générique, désigne un jeu minimal, de sorte que le premier match est la suivante:

first matched here 

... au lieu de ceci:

first matched hereXYZ 
and then 
again ABCsecond match 
+0

@Sonam - Dépend de la syntaxe regex utilisée - rappelez-vous, nous avons basique, étendu, et compatible avec Perl; seul le dernier reconnaît le point d'interrogation comme modifiant le comportement cupide. –

+0

.? correspondrait à zéro ou un charachter - vous avez également besoin * ou + –

+0

Merci les gars. Oui, bien sûr, il devrait être. *? ou. +? ... mon regex-fu est faible, et son PCRE :) –

0

Vous voulez le match non gourmand, .*?

while($string =~ /ABC(.*?)XYZ/gm) { 
    $match = $1; 
} 
+0

(ce perl .. Il y a une raison pour laquelle tant de langues utilisent perl style regex ...). ;-) –

Questions connexes