日期:2011-07-28 浏览次数:20477 次
  规则表达式的知识可能是不少编程人员“常学常忘”的知识之一。在这篇文章中,我们将假定你已经掌握了规则表达式的用法,尤其是Perl 5中表达式的用法。.NET的regexp类是Perl 5中表达式的一个超集,因此,从理论上说它将作为一个很好的起点。我们还假设你具有了C#的语法和.NET架构的基本知识。 
   
  如果你没有规则表达式方面的知识,我建议你从Perl 5的语法着手开始学习。在规则表达式方面的权威书籍是由杰弗里·弗雷德尔编写的《掌握表达式》一书,对于希望深刻理解表达式的读者,我们强烈建议阅读这本书。 
   
RegularExpression组合体
regexp规则类包含在System.Text.RegularExpressions.dll文件中,在对应用软件进行编译时你必须引用这个文件,例如:
csc r:System.Text.RegularExpressions.dll foo.cs
命令将创建foo.exe文件,它就引用了System.Text.RegularExpressions文件。 
   
名字空间简介
  在名字空间中仅仅包含着6个类和一个定义,它们是: 
   
  Capture: 包含一次匹配的结果; 
  CaptureCollection: Capture的序列; 
  Group: 一次组记录的结果,由Capture继承而来; 
  Match: 一次表达式的匹配结果,由Group继承而来; 
  MatchCollection: Match的一个序列; 
  MatchEvaluator: 执行替换操作时使用的代理; 
  Regex: 编译后的表达式的实例。
Regex类中还包含一些静态的方法:
  Escape: 对字符串中的regex中的转义符进行转义; 
  IsMatch: 如果表达式在字符串中匹配,该方法返回一个布尔值; 
  Match: 返回Match的实例; 
  Matches: 返回一系列的Match的方法; 
  Replace: 用替换字符串替换匹配的表达式; 
  Split: 返回一系列由表达式决定的字符串; 
  Unescape:不对字符串中的转义字符转义。 
   
简单匹配
  我们首先从使用Regex、Match类的简单表达式开始学习。 
   
Match m = Regex.Match("abracadabra", "(a|b|r)+"); 
   
我们现在有了一个可以用于测试的Match类的实例,例如:if (m.Success)... 
如果想使用匹配的字符串,可以把它转换成一个字符串: 
   
Console.WriteLine("Match="+m.ToString()); 
   
这个例子可以得到如下的输出: Match=abra。这就是匹配的字符串了。 
   
字符串的替换
  简单字符串的替换非常直观。例如下面的语句: 
   
string s = Regex.Replace("abracadabra", "abra", "zzzz"); 
   
它返回字符串zzzzcadzzzz,所有匹配的字符串都被替换成了zzzzz。 
  现在我们来看一个比较复杂的字符串替换的例子: 
   
string s = Regex.Replace(" abra ", @"^\s*(.*?)\s*$", "$1"); 
   
这个语句返回字符串abra,其前导和后缀的空格都去掉了。 
   
  上面的模式对于删除任意字符串中的前导和后续空格都非常有用。在C#中,我们还经常使用字母字符串,在一个字母字符串中,编译程序不把字符“ \” 作为转义字符处理。在使用字符“\”指定转义字符时,@"..."是非常有用的。另外值得一提的是$1在字符串替换方面的使用,它表明替换字符串只能包含被替换的字符串。 
   
匹配引擎的细节
  现在,我们通过一个组结构来理解一个稍微复杂的例子。看下面的例子: 
   
string text = "abracadabra1abracadabra2abracadabra3"; 
   
    string pat = @" 
   
      ( # 第一个组的开始 
   
       abra # 匹配字符串abra 
   
       ( # 第二个组的开始 
   
       cad # 匹配字符串cad 
   
       )? # 第二个组结束(可选) 
   
      ) # 第一个组结束 
   
      + # 匹配一次或多次 
   
      "; 
   
    //利用x修饰符忽略注释 
   
    Regex r = new Regex(pat, "x"); 
   
    //获得组号码的清单 
   
    int[] gnums = r.GetGroupNumbers(); 
   
    //首次匹配 
   
    Match m = r.Match(text); 
   
    while (m.Success) 
   
     { 
   
    //从组1开始 
   
     for (int i = 1; i < gnums.Length; i++) 
   
      { 
   
      Group g = m.Group(gnums[i]); 
   
    //获得这次匹配的组 
   
      Console.WriteLine("Group"+gnums[i]+"=["+g.ToString()+"]"); 
   
    //计算这个组的起始位置和长度 
   
      CaptureCollection cc = g.Captures; 
   
      for (int j = 0; j < cc.Count; j++) 
   
       { 
   
       Capture c = cc[j]; 
   
       Console.WriteLine(" C