括号

  正则表达式中的括号能将多个字符或者表达式当做一组,即将他们看成一个整体。这样量词就可以修饰这一组表达式。阅读本章前,建议先下载我于CSDN上传的示例代码,下载无需分数,下载链接

1.分组

  假设我们要匹配偶数个数字,如何匹配?尝试"^\d{2}+$"来匹配。"\d{2}"匹配2个数字,"+"匹配至少一次,两者组合起来应该是偶数个数字。但是由下例可看出这个正则表达式并不合法。只能尝试修改这个正则表达式为"^(\d{2})+$"。将"\d{2}"看做一个分组,再来使用量词。

  1. Regex.IsMatch("",@"^\d{2}+$");
  2. //抛出异常:System.ArgumentException
  3. //异常信息:正在分析“^\d{2}+$”- 嵌套限定符 +。
  4. Regex.IsMatch("",@"^(\d{2})+$");//true

2.捕获分组

  捕获分组十分有用,他可以捕获匹配正则表达式的子字符串。分组其实是带有捕获功能的,例如分组"(\d)"匹配呢数字"5",则可以通过匹配对象获得"5"这个值。现在有几个匹配日期格式的正则表达式"(\d{4}-\d{2}-\d{2})","(\d{4}-\d{2})-\d{2}","(\d{4})-(\d{2})-(\d{2})"和一个十分没有规律的输入字符串"2015-06-15-20-30-2014-02-28-01-015-2015-08-09-00"。我们要从中提取出一些日期,不同的正则表达式会让程序输出不同的结果,但是他们均会匹配出他们想要的三个日期。"2015-06-15","2014-02-28","2015-08-09"。

  1. //一个用于输出匹配子字符串的辅助方法
  2. public static void ShowAllMatch(Match match, bool isCapture)
  3. {
  4. int MatchCount = ;//匹配次数
  5. while (true)
  6. {
  7. if (match.Success)
  8. {
  9. MatchCount++;
  10. Console.WriteLine("第{0}个匹配的字符串为:{1}", MatchCount.ToString(), match.Value);
  11. int GroupIndex = ;
  12. /*
  13. * 对于任意一个Match对象,其Gruops集合中至少有一个元素,下标为0。
  14. * 若Match对象能成功匹配子字符串,则下标0的位置默认存储整个匹配的字符串。若不成功则为空。
  15. * 若通过下标寻找不存在的项,则只返回空字符串,不会报错。
  16. * 其余下标对应正则表达式中括号出现的位置。如第一个Gruops[1],对应匹配第一个括号的分组。
  17. */
  18. foreach (Group group in match.Groups)
  19. {
  20. Console.WriteLine("分组下标:{0},分组的值为:{1}", GroupIndex.ToString(), group.Value);
  21. /*
  22. * 当在括号分组后加上量词时(如'(\d){m,n}'这种形式),可通过Capture类获得每一次捕获的字符串。
  23. * 如,若匹配了字符串"2015",则Capture会分别捕获,"2","0","1","5",group.Value的值为"5"
  24. * 此时,group.Value仅获取最后捕获的子字符串。
  25. */
  26. if (isCapture)
  27. {
  28. int CaptureIndex = ;
  29. foreach (Capture capture in group.Captures)
  30. {
  31. Console.WriteLine("分组下标:{0},第{1}个捕获的子字符串为:{2}", GroupIndex.ToString(), CaptureIndex.ToString(), capture.Value);
  32. CaptureIndex++;
  33. }
  34. }
  35. GroupIndex++;
  36. }
  37. match = match.NextMatch();//获取从该匹配位置结束之后的下一个匹配对象。
  38. Console.WriteLine();
  39. }
  40. else
  41. {
  42. if (MatchCount == )
  43. Console.WriteLine("没有匹配项!");
  44. else
  45. Console.WriteLine("匹配结束!");
  46. break;
  47. }
  48. }
  49. }
  50.  
  51. /*Main方法中的调用*/
  52.  
  53. Console.WriteLine("---捕获分组示例1---");
  54. string InputB = "2015-06-15-20-30-2014-02-28-01-015-2015-08-09-00";
  55. string RegexStrB = @"(\d{4})-(\d{2})-\d{2}";//匹配一个日期,格式为YYYY-MM-DD。再通过分组获取匹配字符串中的年份和月份。
  56. Regex RegexB = new Regex(RegexStrB);
  57. Match MatchB = RegexB.Match(InputB);
  58. ShowAllMatch(MatchB, false);
  59. Console.WriteLine();
  60.  
  61. Console.WriteLine("---捕获分组示例2---");
  62. string InputC = "2015-06-15-20-30-2014-02-28-01-015-2015-08-09-00";
  63. string RegexStrC = @"(\d){4}-(\d){2}-\d{2}";//匹配一个日期,格式为YYYY-MM-DD。再通过分组获取匹配字符串中的年份和月份。
  64. Regex RegexC = new Regex(RegexStrC);
  65. Match MatchC = RegexC.Match(InputC);
  66. ShowAllMatch(MatchC, true);
  67. Console.WriteLine();
  68.  
  69. Console.WriteLine("---捕获分组示例3---");
  70. string InputD = "2015-06-15-20-30-2014-02-28-01-015-2015-08-09-00";
  71. /*
  72. * 匹配一个日期,格式为YYYY-MM-DD。再通过分组获取匹配字符串中的年份和月份。
  73. * 若括号之间有嵌套,则Group的下标先算外层括号,再算内层。
  74. */
  75. string RegexStrD = @"((\d){4}-(\d){2})-(\d){2}";
  76. Regex RegexD = new Regex(RegexStrD);
  77. Match MatchD = RegexD.Match(InputD);
  78. ShowAllMatch(MatchD, true);
  79. Console.WriteLine();

  以上代码由各位复制到自己的机器查看运行结果。以下代码给出直观的捕获匹配值的例子。

  1. Regex regex = new Regex(@"(\d{4}-\d{2}-\d{2})");
  2. Match match = regex.Match("2015-06-15-20-30-2014-02-28-01-015-2015-08-09-00");
  3. while(true)
  4. {
  5. if (match.Success)
  6. {
  7. Console.WriteLine(match.Value);
  8. match = match.NextMatch();//匹配下一个符合的子字符串
  9. }
  10. else
  11. break;
  12. }
  13.  
  14. //一共输出3个结果。
  15. //2015-06-15
  16. //2014-02-28
  17. //2015-08-09

  Match类是匹配结果的对象。可通过Match.Success判断匹配是否成功,通过Match.Value来获得符合匹配的子字符串。

3.反向引用

  如果我们要判断一个英文单词是否有相邻两个字母重复。例如"book","sleep"等。我们可以使用反向引用这个特性。其正则表达式语法"(regStr)\num",其中regStr为子正则表达式,num为需要引用的括号的位置。

  1. Regex regex = new Regex(@"([a-z])\1");
  2. regex.IsMatch("book");//true
  3. regex.IsMatch("sleep");//true
  4. regex.IsMatch("where");//false

  由于\num容易引起不确定,因为有可能转换为对应的ascii码。所以.NET还可以以"(regStr)\k<num>"这样的语法确保反向引用。

  1. Regex regex = new Regex(@"([a-z])\k<1>");
  2. regex.IsMatch("book");//true
  3. regex.IsMatch("sleep");//true
  4. regex.IsMatch("where");//false

4.命名分组

  当分组太多的时候,容易出现计算分组下标错误的情况。因此可以给分组命名,直接通过名字来获取分组的值。正则表达式语法"(?<name>regStr)",name的值由你自己决定。

  1. Regex regex = new Regex(@"(?<Year>\d{4})-(?<Month>\d{2})-(?<Day>\d{2})");
  2. Match match = regex.Match("2015-06-15");
  3. Console.WriteLine(match.Groups["Day"].Value);//"15"
  4. Console.WriteLine(match.Groups["Year"].Value);//"2015"
  5. Console.WriteLine(match.Groups["Month"].Value);//"06"
  6. //也可以使用下标查找,并不影响。
  7. Console.WriteLine(match.Groups[].Value);//"2015-06-15"
  8. Console.WriteLine(match.Groups[].Value);//"2015"
  9. Console.WriteLine(match.Groups[].Value);//"06"
  10. Console.WriteLine(match.Groups[].Value);//"15"

5.非捕获分组

  由于捕获会造成性能的损耗,当我们仅想将多个正则表达式组成一组而不想捕获他的值时,可使用非捕获分组。正则表达式语法"(?:regStr)"。

  1. Regex regex = new Regex(@"(?:\d{4})-(?:\d{2})-(?:\d{2})");
  2. Match match = regex.Match("2015-06-15");
  3. Console.WriteLine(match.Groups[].Value);//"2015-06-15"
  4. Console.WriteLine(match.Groups[].Value);// "" 没有值,但是不会报错
  5. Console.WriteLine(match.Groups[].Value);// "" 没有值,但是不会报错
  6. Console.WriteLine(match.Groups[].Value);// "" 没有值,但是不会报错

6.贪婪匹配与懒惰匹配

  对于一个输入字符串"123456789",如果用"(\d*)"来匹配,则整个字符串都将被捕获了。我们可以看出这个正则表达式十分贪婪,如果输入一个一百位的数字他也是会捕获回来的。如果我们要尽可能少的捕获子字符串呢?那么可以在量词后添加"?",懒惰匹配正则表达式语法"regStr{n,m}?"。

  1. Regex regex = new Regex(@"\d{2,5}");
  2. Match match = regex.Match("");
  3. Console.WriteLine(match.Value);//"12345"
  4. regex = new Regex(@"\d{2,5}?");
  5. match = regex.Match("");
  6. Console.WriteLine(match.Value);//"12"
  7. match = match.NextMatch();
  8. Console.WriteLine(match.Value);//"34"

  分组括号暂时介绍这么多,谢谢!

.NET正则表达式基础入门(三)的更多相关文章

  1. .NET正则表达式基础入门

    这是我第一次写的博客,个人觉得十分不容易.以前看别人写的博客文字十分流畅,到自己来写却发现十分困难,还是感谢那些为技术而奉献自己力量的人吧. 本教程编写之前,博主阅读了<正则指引>这本入门 ...

  2. Swift语法基础入门三(函数, 闭包)

    Swift语法基础入门三(函数, 闭包) 函数: 函数是用来完成特定任务的独立的代码块.你给一个函数起一个合适的名字,用来标识函数做什么,并且当函数需要执行的时候,这个名字会被用于“调用”函数 格式: ...

  3. C#基础入门 三

    C#基础入门 三 类 类使用class关键字进行声明,前面加一个访问修饰符,public class car{} 访问修饰符:修师傅可以用来修饰类和类成员等,控制它们的可见度 修饰符关键字分别为:pu ...

  4. .NET正则表达式基础入门(二)

    量词 正则表达式的量词用于表明前面的子表达式需要匹配的次数.阅读本章前,建议先下载我于CSDN上传的示例代码,下载无需分数,下载链接. 1.量词的一般形式 "{n}"," ...

  5. PHP正则表达式基础入门

    思维导图 介绍 正则表达式,大家在开发中应该是经常用到,现在很多开发语言都有正则表达式的应用,比如JavaScript.Java..Net.PHP 等,我今天就把我对正则表达式的理解跟大家唠唠,不当之 ...

  6. .NET正则表达式基础入门(四)

    断言 判断某个位置左侧或者右侧是否符合匹配.常见断言有三种,单词边界.行起始/结束位置.环视.阅读本章前,建议先下载我于CSDN上传的示例代码,下载无需分数,下载链接. 1.单词边界 正则表达式&qu ...

  7. .NET正则表达式基础入门(一)

    字符组 正则表达式的字符组十分简单,就是列出你所想要匹配的字符.阅读本章前,建议先下载我于CSDN上传的示例代码,下载无需分数,下载链接. 1.普通字符组 普通字符组,列出所有你需要匹配的字符. 例如 ...

  8. Oracle基础入门(三)

    一:PLsql一些基本操作 调节plsql的字体大小 二:创建表,如果学过sql server的数据库就会发现其实Oracle跟的一些新建表和新增修改其实是差不多的 新建表 Create table ...

  9. C#学习笔记---基础入门(三)

    泛型<T> 使用泛型能够最大限度的重用代码/保护类型安全,提高性能 泛型成员因为类型的不确定性,不能使用算术运算符/比较运算符 类型参数可以有多个,可以是编译器能够识别的任何类型 类型参数 ...

随机推荐

  1. Web应用程序的自动化测试库-FluentAutomation

    FluentAutomation是流畅的自动化应用编程接口,支持Selenium和WatiN 连同它们所有的风格和驱动程序.自从Fluient支持Selenium,那就意味着你可以使用Selenium ...

  2. HTML5- Canvas入门(一)

    周老虎落网的时候,网易跟腾讯都推出了牛逼轰轰的HTML5页面来展示其关系网(网易http://news.163.com/special/data_zyk/  ,腾讯http://news.qq.com ...

  3. ASP.NET安全

    ASP.NET 安全 概述 安全在web领域是一个永远都不会过时的话题,今天我们就来看一看一些在开发ASP.NET MVC应用程序时一些值得我们注意的安全问题.本篇主要包括以下几个内容 : 认证 授权 ...

  4. gulp使用小结(一)

    这篇文章不会介绍 gulp 的起源.发展:不会去一个个讲解 gulp API:也不想出现大段大段的 gulpfile.js 代码:更木有帮你分析 gulp 实现原理,只有一些我自己对 gulp 的使用 ...

  5. java中构造方法的特殊性

    构造方法名与类名相同 构造方法没有返回值,也不能写void 构造方法的主要作用是完成对对象的初始化工作 构造方法一般不由编程人员显示调用,而是由new来调用 在创建一个类的对象的同时,系统会自动调用该 ...

  6. [大数据之Spark]——Transformations转换入门经典实例

    Spark相比于Mapreduce的一大优势就是提供了很多的方法,可以直接使用:另一个优势就是执行速度快,这要得益于DAG的调度,想要理解这个调度规则,还要理解函数之间的依赖关系. 本篇就着重描述下S ...

  7. 微信蓝牙设备开发教程之获取设备deviceid和二维码(3)

    文章转载地址  http://www.vxzsk.com/87.html  设备授权 调用 设备授权新接口 ,获取deviceid和二维码,然后利用获取到的deviceid更新设备属性(如mac地址, ...

  8. 工作任务:模拟淘宝登录和购物车功能:使用cookie记录登录名,下次登录时能够记得上次的登录名,使用cookie模拟购物车功能,使用session记住登录信息并验证是否登录,防止利用url打开网站,并实现退出登录功能

    登入界面<% Cookie[] cks =request.getCookies(); String str=null; for(Cookie ck:cks) { if(ck.getName(). ...

  9. Event的Propagate

    SSIS Package的Executable存在层次结构,例如Package位于层次结构的最顶层,Root Level:Container是其中包含的Executable(Task 或 Contai ...

  10. LINQ系列:LINQ to XML操作

    LINQ to XML操作XML文件的方法,如创建XML文件.添加新的元素到XML文件中.修改XML文件中的元素.删除XML文件中的元素等. 1. 创建XML文件 string xmlFilePath ...