2013-01-22 76 views
1

我必须编写正则表达式才能从文本中获取三个单词。单词用一个空格分隔。我写的代码并不是所有的序列。例如,对于文本“一二三四五六”,我只得到了两个序列:1.一个两个三个2.四个五六个。但我希望我的正则表达式给我所有的序列,所以输出结果是:1.一两三3.二三四3.三四五。四,五六。 有人可以告诉我,我的正则表达式有什么问题吗? 这里是我的代码:从文本中获取3个单词

string input = "one two three four five six"; 
    string pattern = @"([a-zA-Z]+){2}[a-zA-Z]+"; 
    Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase); 
    MatchCollection matches = rgx.Matches(input); 
    if (matches.Count > 0) 
    { 
     Console.WriteLine("{0} ({1} matches):", input, matches.Count); 
     Console.WriteLine(); 
     foreach (Match match in matches) 
      Console.WriteLine(match.Value); 
    } 
    Console.ReadLine(); 
+0

我不明白这个问题。对我来说,所有的序列将是*一二三*,*两三四*,*三四五*和*四五六* – m0skit0

+0

是的,你是赖特,我很抱歉。我想得到所有的序列: 一二三三二三四三五五四五六。 我已经编辑了我的问题 – Yarik

+0

我不认为你只用一个正则表达式和一个迭代就可以做你想做的事。 – m0skit0

回答

5

没有什么不对您的正则表达式 - 它的表情是多么的正常工作。当你找到一场比赛时,搜索下一场比赛继续在结束,你刚刚找到一个 - 比赛的宽度是消耗

那么,如何解决这个问题呢?一种方法是让你的比赛不消耗任何东西。您可以将您的原有格局在零宽度正预测先行断言做到这一点:

string pattern = @"(?=([a-zA-Z]+){2}[a-zA-Z]+)"; 
added --->   ***      * 

(?=pattern)说:“在这一点上唯一的比赛,如果它紧跟soemthing匹配pattern” - 但内容匹配pattern ISN”这是整个比赛的一部分,所以不会被消耗。

如果它不是匹配的一部分,但它不会出现在match.Value - 那么您如何获得价值呢?简单 - 只需在原始模式周围添加一个捕捉组(即(?=(pattern))),捕捉的组将正常显示在您的结果中。

string pattern = @"(?=(([a-zA-Z]+){2}[a-zA-Z]+))"; 
added --->   *      * 

所以,现在,你可以像以前一样通过您foreach循环,但match.Value是空的 - 你期望的结果是在match.Groups[1].Value

但现在你又有了一个问题。你的结果是

one two three 
ne two three 
e two three 
two three four 
wo three four 

等等。这是因为即使当您在字词的中途开始时,您的模式仍匹配

如何解决这个问题?

我们添加另一个零宽度断言,这个时候负回顾后(?<![a-zA-Z])。而不是说“如果这个点跟随的模式只匹配”,它说“从来没有匹配,如果这个点是先于的模式”。因此,我们永远不会在一封信的前面匹配。例如,ne two three不会返回,因为它的前面有o

string pattern = @"(?<![a-zA-Z])(?=(([a-zA-Z]+){2}[a-zA-Z]+))"; 
added --->   ************* 

有了这种模式,你终于得到了预期的结果。

+0

做得好先生:) –

+0

非常感谢你!有用! – Yarik

+1

@Yarik很高兴听到它;我希望你可以带走一些东西,并在未来的不同情况下使用它:) – Rawling

相关问题