2012-09-11 54 views
0

我有一个文本文件是这样的:正则表达式 - MatchCollection让子匹配

Start 
<Not Present> 

    Start 
    <Word> 
    End 

    Start 
    <Word> 
    End 

    Start 
    <Antoher> 
    End  

End 

我必须写一个正则表达式提供的结果只包含<Word>“开始......结束”块。

我已经尝试过的东西像这样:

(Start[\s\S]+?(<Word>.*)[\s\S]+?End) 

,我得到两个子匹配的结果。 第一子匹配:

Start 
<Not Present> 

    Start 
    <Word> 
    End 

二子匹配:

Start 
    <Word> 
    End 

正如你所看到的,第二个是正确的,但第一个是错误的。我只想要<Word>位于“Start ... End”块内的子匹配。

我该怎么做?

谢谢。

回答

1
(?s)Start(?:(?!Start|End).)*<Word>(?:(?!End).)*End 

(?!Start|End).任何一个字符(包括\n,由于(?s)改性剂)相匹配,除非它是StartEnd第一个字符。这确保您只匹配StartEnd分隔符的最内层集合。

我在单线模式(通过内联(?s)改性剂)使用.匹配任何字符包括换行因为你提到MatchCollection,表明你正在使用的.NET正则表达式的味道。那个[\s\S]黑客通常只在JavaScript中需要。


更正:我曾以为你在谈论从.NET框架类System.Text.RegularExpressions.MatchCollection,但我刚刚了解到,VBScript中还含有一种叫MatchCollection类。这也可能是你使用VBScript的味道(通过ActiveX或COM),因此正则表达式应该是:

Start(?:(?!Start|End)[\S\s])*<Word>(?:(?!End)[\S\s])*End 

很抱歉的混乱。更多信息可用here

+0

是否有可能在VB6中我不能使用(?)内联修饰符? – epi82

+0

VB6是一种.NET语言吗?我不记得了。如果不是,它将遵循与VBScript/JavaScript/ECMAScript相同的规则,并且您必须使用'[\ S \ s]'。 –

0

两个问题:

  1. 您使用的是“贪婪”的比赛 - 只需添加一个?,使其非贪婪。没有这一点,它会匹配一个StartEnd跨越双 - 第一Start和第二End - 并把它在开始和<Word>
  2. 表达[\s\S]结束两场比赛的一切 - 这是一样的一个点.。你只想要空格[\s]

试试这个(你可以删除多余的外括号太):

Start(.*?<Word>.*?)End 
+0

上面的代码是一个例子...不幸的是只有空白[\ s]是不够的。有可能是像开始结束...如何解决它? – epi82

+0

我的正则表达式处理:'。*? 。*?'的意思是“输入中的任何地方”,但非贪婪。我编辑了正则表达式来删除不相关的空格匹配 – Bohemian

0

[\s\S]没有太大的意义。 \s与空格匹配,而\S完全相反 - 匹配非空格。所以[\s\S]几乎等于.

我也不确定在<Word>之后您想用.*达到什么目的。这只会匹配<Word>之后的空格。

(Start[\s]+(<Word>)[\s]+End) 

据我所知,它可以在你的测试用例http://regexpal.com/上运行。