C#正则表达式:group和capture

来源:互联网 发布:安卓乐器软件 编辑:程序博客网 时间:2024/05/16 14:58

  1. /// <summary>  
  2. /// 显示Match内多个Group的例子  
  3. /// </summary>  
  4. public void ShowStructure()  
  5. {  
  6.     //要匹配的字符串  
  7.     string text = "1A 2B 3C 4D 5E 6F 7G 8H 9I 10J 11Q 12J 13K 14L 15M 16N ffee80 #800080";  
  8.     //正则表达式  
  9.     string pattern = @"((/d+)([a-z]))/s+";  
  10.     //使用RegexOptions.IgnoreCase枚举值表示不区分大小写  
  11.     Regex r = new Regex(pattern, RegexOptions.IgnoreCase);  
  12.     //使用正则表达式匹配字符串,仅返回一次匹配结果  
  13.     Match m = r.Match(text);  
  14.     while (m.Success)  
  15.     {  
  16.         //显示匹配开始处的索引值和匹配到的值  
  17.         System.Console.WriteLine("Match=[" + m + "]");  
  18.         CaptureCollection cc = m.Captures;  
  19.         foreach (Capture c in cc)  
  20.         {  
  21.             Console.WriteLine("/tCapture=[" + c + "]");  
  22.         }  
  23.         for (int i = 0; i < m.Groups.Count; i++)  
  24.         {  
  25.             Group group = m.Groups[i];  
  26.             System.Console.WriteLine("/t/tGroups[{0}]=[{1}]", i, group);  
  27.             for (int j = 0; j < group.Captures.Count; j++)  
  28.             {  
  29.                 Capture capture = group.Captures[j];  
  30.                 Console.WriteLine("/t/t/tCaptures[{0}]=[{1}]", j, capture);  
  31.             }  
  32.         }  
  33.         //进行下一次匹配.  
  34.         m = m.NextMatch();  
  35.     }  
  36. }  

这段代码的执行效果如下:
Match=[1A ]
    Capture=[1A ]
        Groups[0]=[1A ]
            Captures[0]=[1A ]
        Groups[1]=[1A]
            Captures[0]=[1A]
        Groups[2]=[1]
            Captures[0]=[1]
        Groups[3]=[A]
            Captures[0]=[A]
Match=[2B ]
    Capture=[2B ]
        Groups[0]=[2B ]
            Captures[0]=[2B ]
        Groups[1]=[2B]
            Captures[0]=[2B]
        Groups[2]=[2]
            Captures[0]=[2]
        Groups[3]=[B]
            Captures[0]=[B]
..................此去省略一些结果
Match=[16N ]
    Capture=[16N ]
        Groups[0]=[16N ]
            Captures[0]=[16N ]
        Groups[1]=[16N]
            Captures[0]=[16N]
        Groups[2]=[16]
            Captures[0]=[16]
        Groups[3]=[N]
            Captures[0]=[N]
通过对上面的代码结合代码的分析,我们得出下面的结论,在((/d+)([a-z]))/s+这个正则表达式里总共包含了四个Group,即分组,按照默认的从左到右的匹配方式,其中Groups[0]代表了整个分组,其它的则是子分组,用示意图表示如下:
Group分组之间的关系 
在上面的代码中是采用了Regex类的Match()方法,调用这种方法返回的是一个Match,要处理分析全部的字符串,还需要在while循环的中通过Match类的NextMatch()方法返回下一个可能成功的匹配(可通过Match类的Success属性来判断是否成功匹配)。上面的代码还可以写成如下形式:

[c-sharp] view plaincopy
  1. /// <summary>  
  2. /// 使用Regex类的Matches方法所有所有的匹配  
  3. /// </summary>  
  4. public void Matches()  
  5. {  
  6.     //要匹配的字符串  
  7.     string text = "1A 2B 3C 4D 5E 6F 7G 8H 9I 10J 11Q 12J 13K 14L 15M 16N ffee80 #800080";  
  8.     //正则表达式  
  9.     string pattern = @"((/d+)([a-z]))/s+";  
  10.     //使用RegexOptions.IgnoreCase枚举值表示不区分大小写  
  11.     Regex r = new Regex(pattern, RegexOptions.IgnoreCase);  
  12.     //使用正则表达式匹配字符串,返回所有的匹配结果  
  13.     MatchCollection matchCollection = r.Matches(text);  
  14.     foreach (Match m in matchCollection)  
  15.     {  
  16.         //显示匹配开始处的索引值和匹配到的值  
  17.         System.Console.WriteLine("Match=[" + m + "]");  
  18.         CaptureCollection cc = m.Captures;  
  19.         foreach (Capture c in cc)  
  20.         {  
  21.             Console.WriteLine("/tCapture=[" + c + "]");  
  22.         }  
  23.         for (int i = 0; i < m.Groups.Count; i++)  
  24.         {  
  25.             Group group = m.Groups[i];  
  26.             System.Console.WriteLine("/t/tGroups[{0}]=[{1}]", i, group);  
  27.             for (int j = 0; j < group.Captures.Count; j++)  
  28.             {  
  29.                 Capture capture = group.Captures[j];  
  30.                 Console.WriteLine("/t/t/tCaptures[{0}]=[{1}]", j, capture);  
  31.             }  
  32.         }  
  33.     }  
  34. }  

上面的这段代码和采用While循环遍历所有匹配的结果是一样的,在实际情况中有可能出现不需要全部匹配而是从某一个位置开始匹配的情况,比如从第32个字符处开始匹配,这种要求可以通过Match()或者Matches()方法的重载方法来实现,仅需要将刚才的实例代码中的MatchCollection matchCollection = r.Matches(text);改为MatchCollection matchCollection = r.Matches(text,48);就可以了。

输出结果如下:
Match=[5M ]
        Capture=[5M ]
                Groups[0]=[5M ]
                        Captures[0]=[5M ]
                Groups[1]=[5M]
                        Captures[0]=[5M]
                Groups[2]=[5]
                        Captures[0]=[5]
                Groups[3]=[M]
                        Captures[0]=[M]
Match=[16N ]
        Capture=[16N ]
                Groups[0]=[16N ]
                        Captures[0]=[16N ]
                Groups[1]=[16N]
                        Captures[0]=[16N]
                Groups[2]=[16]
                        Captures[0]=[16]
                Groups[3]=[N]
                        Captures[0]=[N]
注意上面的MatchCollection matchCollection = r.Matches(text,48)表示从text字符串的位置48处开始匹配,要注意位置0位于整个字符串的之前,位置1位于字符串中第一个字符之后第二个字符之前,示意图如下(注意是字符串“1A”与“2B”之间有空格):
索引与字符串的关系 
在text的位置48处正好是15M中的5处,因此返回的第一个Match是5M而不是15M。这里还继续拿出第一篇中的图来,如下:
.NET中正则表达式类之间的关系 
从上图可以看出Capture、Group及Match类之间存在继承关系,处在继承关系顶端的Capture类中就定义了Index、Length和Value属性,其中Index表示原始字符串中发现捕获子字符串的第一个字符的出现位置,Length属性表示子字符串的长度,而Value属性表示从原始字符串中捕获的子字符串,利用这些属性可以实现一些比较复杂的应用。