您的位置: 首页 > 技术文档 > 网络编程 > 解读 C# 中的正则表达式
用Dreamweaver MX设计超简留言本 回到列表 Microsoft Access数据库常规规格
 解读 C# 中的正则表达式

作者:刘彦青 时间: 2004-01-15 文档类型:翻译 来自:蓝色理想

第 1 页 解读 C# 中的正则表达式
第 2 页 常用表达式

  多少年来,许多的编程语言和工具都包含对正则表达式的支持,.NET基础类库中包含有一个名字空间和一系列可以充分发挥规则表达式威力的类,而且它们也都与未来的Perl 5中的规则表达式兼容。 
  
  此外,regexp类还能够完成一些其他的功能,例如从右至左的结合模式和表达式的编辑等。 
  
  在这篇文章中,我将简要地介绍System.Text.RegularExpression中的类和方法、一些字符串匹配和替换的例子以及组结构的详细情况,最后,还会介绍一些你可能会用到的常见的表达式。 
  
应该掌握的基础知识

  规则表达式的知识可能是不少编程人员“常学常忘”的知识之一。在这篇文章中,我们将假定你已经掌握了规则表达式的用法,尤其是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(" Capture" + j + "=["+c.ToString()
  
         + "] Index=" + c.Index + " Length=" + c.Length);
  
       }
  
      }
  
    //下一个匹配
  
     m = m.NextMatch();
  
     }
 
   
 这个例子的输出如下所示:
     
    Group1=[abra]
  
        Capture0=[abracad] Index=0 Length=7
  
        Capture1=[abra] Index=7 Length=4
  
    Group2=[cad]
  
        Capture0=[cad] Index=4 Length=3
  
    Group1=[abra]
  
        Capture0=[abracad] Index=12 Length=7
  
        Capture1=[abra] Index=19 Length=4
  
    Group2=[cad]
  
        Capture0=[cad] Index=16 Length=3
  
    Group1=[abra]
  
        Capture0=[abracad] Index=24 Length=7
  
        Capture1=[abra] Index=31 Length=4
  
    Group2=[cad]
  
        Capture0=[cad] Index=28 Length=3

  我们首先从考查字符串pat开始,pat中包含有表达式。第一个capture是从第一个圆括号开始的,然后表达式将匹配到一个abra。第二个capture组从第二个圆括号开始,但第一个capture组还没有结束,这意味着第一个组匹配的结果是abracad ,而第二个组的匹配结果仅仅是cad。因此如果通过使用?符号而使cad成为一项可选的匹配,匹配的结果就可能是abra或abracad。然后,第一个组就会结束,通过指定+符号要求表达式进行多次匹配。 
  
  现在我们来看看匹配过程中发生的情况。首先,通过调用Regex的constructor方法建立表达式的一个实例,并在其中指定各种选项。在这个例子中,由于在表达式中有注释,因此选用了x选项,另外还使用了一些空格。打开x选项,表达式将会忽略注释和其中没有转义的空格。 
  
  然后,取得表达式中定义的组的编号的清单。你当然可以显性地使用这些编号,在这里使用的是编程的方法。如果使用了命名的组,作为一种建立快速索引的途径这种方法也十分有效。 
  
  接下来是完成第一次匹配。通过一个循环测试当前的匹配是否成功,接下来是从group 1开始重复对组清单执行这一操作。在这个例子中没有使用group 0的原因是group 0是一个完全匹配的字符串,如果要通过收集全部匹配的字符串作为一个单一的字符串,就会用到group 0了。 
  
  我们跟踪每个group中的CaptureCollection。通常情况下每次匹配、每个group中只能有一个capture,但本例中的Group1则有两个capture:Capture0和Capture1。如果你仅需要Group1的ToString,就会只得到abra,当然它也会与abracad匹配。组中ToString的值就是其CaptureCollection中最后一个Capture的值,这正是我们所需要的。如果你希望整个过程在匹配abra后结束,就应该从表达式中删除+符号,让regex引擎知道我们只需要对表达式进行匹配。 
  
基于过程和基于表达式方法的比较

  一般情况下,使用规则表达式的用户可以分为以下二大类:第一类用户尽量不使用规则表达式,而是使用过程来执行一些需要重复的操作;第二类用户则充分利用规则表达式处理引擎的功能和威力,而尽可能少地使用过程。 
  
  对于我们大多数用户而言,最好的方案莫过于二者兼而用之了。我希望这篇文章能够说明.NET语言中regexp类的作用以及它在性能和复杂性之间的优、劣点。 
  
基于过程的模式

  我们在编程中经常需要用到的一个功能是对字符串中的一部分进行匹配或其他一些对字符串处理,下面是一个对字符串中的单词进行匹配的例子:

string text = "the quick red fox jumped over the lazy brown dog.";
  
    System.Console.WriteLine("text=[" + text + "]");
  
    string result = "";
  
    string pattern = @"\w+|\W+";
  
    foreach (Match m in Regex.Matches(text, pattern))
  
     {
  
    // 取得匹配的字符串
  
     string x = m.ToString();
  
    // 如果第一个字符是小写
  
     if (char.IsLower(x[0]))
  
    // 变成大写
  
      x = char.ToUpper(x[0]) + x.Substring(1, x.Length-1);
  
    // 收集所有的字符
  
     result += x;
  
     }
  
    System.Console.WriteLine("result=[" + result + "]");

   
   正象上面的例子所示,我们使用了C#语言中的foreach语句处理每个匹配的字符,并完成相应的处理,在这个例子中,新创建了一个result字符串。这个例子的输出所下所示: 
  
  text=[the quick red fox jumped over the lazy brown dog.] 
  
  result=[The Quick Red Fox Jumped Over The Lazy Brown Dog.] 
  
基于表达式的模式

  完成上例中的功能的另一条途径是通过一个MatchEvaluator,新的代码如下所示: 
  
static string CapText(Match m)
  
      {
  
    //取得匹配的字符串
  
      string x = m.ToString();
  
    // 如果第一个字符是小写
  
      if (char.IsLower(x[0]))
  
    // 转换为大写
  
       return char.ToUpper(x[0]) + x.Substring(1, x.Length-1);
  
      return x;
  
      }
  
      
  
     static void Main()
  
      {
  
      string text = "the quick red fox jumped over the
  
       lazy brown dog.";
  
      System.Console.WriteLine("text=[" + text + "]");
  
      string pattern = @"\w+";
  
      string result = Regex.Replace(text, pattern,
  
     new MatchEvaluator(Test.CapText));
  
      System.Console.WriteLine("result=[" + result + "]");
  
      }
 
   
  同时需要注意的是,由于仅仅需要对单词进行修改而无需对非单词进行修改,这个模式显得非常简单。

出处:蓝色理想
责任编辑:风狗

上一页 下一页 常用表达式

◎进入论坛网络编程版块参加讨论

相关文章
[asp.net]C#教程
常见 Datagrid 错误
进入 ASP.NET 世界
面向对象的应用服务层设计
作者文章
解读 C# 中的正则表达式
热门搜索:CSS Fireworks 设计比赛 网页制作 Dreamweaver Studio8 Flash
站点最新 站点最新列表
疯狂的程序员 第五十回
疯狂的程序员 第四十九回
疯狂的程序员 第四十八回
疯狂的程序员 第四十七回
疯狂的程序员 第四十六回
疯狂的程序员 第四十五回
疯狂的程序员 第四十四回
疯狂的程序员 第四十三回
疯狂的程序员 第四十二回
疯狂的程序员 第四十一回
栏目最新 栏目最新列表
火星人的耳机
公司正式宣布创业失败
用corelDEAW 12打造唇膏
二行代码解决全部网页木马
一行代码解决iframe挂马
Photoshop制作星空爆炸效果
CorelDraw 12打造休闲裤
Firework如何画特殊的切角图形
Firework打造韩式风格的手提袋
flash实例:打造佛光效果
>> 分页 首页 前页 后页 尾页 页次:1/21个记录/页 转到 页 共2个记录

蓝色理想版权申明:除部分特别声明不要转载,或者授权我站独家播发的文章外,大家可以自由转载我站点的原创文章,但原作者和来自我站的链接必须保留(非我站原创的,按照原来自一节,自行链接)。文章版权归我站和作者共有。

转载要求:转载之图片、文件,链接请不要盗链到本站,且不准打上各自站点的水印,亦不能抹去我站点水印。

特别注意:本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有,文章若有侵犯作者版权,请与我们联系,我们将立即删除修改。

本文现有 1 条评论 评分:- llllllllllllllllllll + 评分人数: 1 ,平均分: 3.00


itmyth Publish at 2005-9-20 13:27:53 评分3
正则表达式技术资料下载 pdf格式
您的评论
用户名:  口令:
说明:输入正确的用户名和密码才能参与评论。如果您不是本站会员,你可以注册 为本站会员。
注意:文章中的链接、内容等需要修改的错误,请用报告错误,以利文档及时修改。
不评分 1 2 3 4 5
注意:请不要在评论中含与内容无关的广告链接,违者封ID
请您注意:
·不良评论请用报告管理员,以利管理员及时删除。
·尊重网上道德,遵守中华人民共和国的各项有关法律法规
·承担一切因您的行为而直接或间接导致的民事或刑事法律责任
·本站评论管理人员有权保留或删除其管辖评论中的任意内容
·您在本站发表的作品,本站有权在网站内转载或引用
·参与本评论即表明您已经阅读并接受上述条款
推荐文档 | 打印文档 | 评论文档 | 报告错误  
专业书推荐 更多内容
大师之路--Photoshop 完全解析
《超越CSS》新书上市
Don't Make Me Think 第2版
HTML与CSS入门经典(第7版)
《FLASH MX2004网站开发精粹》
《CSS入门经典》
《设计师谈网页设计思维》
作品集 更多内容

北京最好的时光即将到来 佳能在线反馈信息 Treasure cute&nbsp;sign Team&nbsp;Toyak OPPO门户网 贵港市财政局 黑色习作