了使用正则表达式,需要把 RegEx 类引入程序。大家可以在 System.Text.RegularExpression 名字域中找到这种类。一旦把这种类导入了程序,就需要决定想要用 RegEx 类来做什么事情了。

如果想要进行匹配,就需要使用 Match类。

如果打算做替换,则不需要 Match 类了。取而代之的是要用到 RegEx 类的 Replace 方法。

5.1.使用正则表达式

  1. Regex reg = new Regex("quick");
  2. string str1 = "the quick brown fox jumped over the lazy dog";
  3. Match matchSet;
  4. int matchPos;
  5. matchSet = reg.Match(str1);
  6. if (matchSet.Success)
  7. {
  8. matchPos = matchSet.Index;
  9. Console.WriteLine("found match at position:" + matchPos);
  10. }
  11.  
  12. //查看是否匹配
  13. bool istrue = Regex.IsMatch(str1, "the");
  14. Console.WriteLine(istrue);
  15.  
  16. //为了处理所有找到的匹配可以把匹配存储到 MatchCollection 对象中
  17. MatchCollection matchSets = reg.Matches(str1);
  18.  
  19. if (matchSets.Count > 0)
  20. {
  21. foreach (Match item in matchSets)
  22. {
  23. Console.WriteLine("found a match at: " + item.Index);
  24. }
  25. }
  26.  
  27. Console.Read();

 

5.2.数量词

代码/语法 说明
* 重复0次或多次
+ 重复一次或多次
重复零次或1次
{n} 重复n次
{n,} 重复至少n次
{n,m} 重复至少n次,但不多于m次

这里要看到的第一个数量词就是加号( +)。这个数量词说明正则表达式应该匹配一个或多个紧接的字符。

  1. Console.WriteLine("ba+: ");
  2. String[] words = new String[] { "bad", "boy", "baaad", "bear", "bend" };
  3.  
  4. foreach (string item in words)
  5. {
  6. if (Regex.IsMatch(item,"ba+"))
  7. {
  8. Console.Write(item+" ");
  9. }
  10. }
  11. Console.WriteLine();
  12. Console.WriteLine("ba*: ");
  13.  
  14. foreach (string item in words)
  15. {
  16. if (Regex.IsMatch(item, "ba*"))
  17. {
  18. Console.Write(item + " ");
  19. }
  20. }
  21. Console.WriteLine();
  22. Console.WriteLine("ba?: ");
  23.  
  24. foreach (string item in words)
  25. {
  26. if (Regex.IsMatch(item, "ba?d"))
  27. {
  28. Console.Write(item + " ");
  29. }
  30. }

 

原本期望这个程序就返回两个标签: <b>和</b>。但是由于贪心,正则表达式匹配了<b>字符串</b>。利用懒惰数量词:问号(?)就可以解决这个问题。当问号直接放在原有数量词后边时,数量词就变懒惰了。这里的懒惰是指在正则表达式中用到的懒惰数量词将试图做尽可能少的匹配,而不是尽可能多的匹配了

  1. string[] words = new string[] { "Part", "of", "this", "<b>string</b>", "is", "bold" };
  2. // 限定符“.” 匹配出换行符以外的任意字符
  3. string regex = "<.*>"; //<b>string</b>
  4. //regex = "<.*?>"; //<b> </b>
  5. MatchCollection collection;
  6. foreach (var item in words)
  7. {
  8. if(Regex.IsMatch(item,regex))
  9. {
  10. collection = Regex.Matches(item, regex);
  11.  
  12. foreach (var value in collection)
  13. {
  14. Console.WriteLine(value);
  15. }
  16.  
  17. }
  18. }

 

5.3.使用字符类

这里第一个要讨论的字符类就是句号( .)。这是一种非常非常容易使用的字符类,但是它也确实是有问题的。句点与字符串中任意字符匹配。

较好利用句点的方法就是用它在字符串内部定义字符范围,也就是用来限制字符串的开始或/和结束字符。

  1. string str1 = "the quick brown fox jumped over the lazy dog one time";
  2. MatchCollection matchSet;
  3. matchSet = Regex.Matches(str1, "t.e");
  4. foreach (Match aMatch in matchSet)
  5. Console.WriteLine("Matches at: " + aMatch.Index);

 

在使用正则表达式的时候经常希望检查包含字符组的模式。大家可以编写用一组闭合的方括号( [ ])包裹着的正则表达式。在方括号内的字符被称为是字符类。如果想要编写的正则表达式匹配任何小写的字母字符,可以写成如下这样的表达式: [abcdefghijklmnopqrstuvwxyz]。但是这样是很难书写的,所以通过连字号: [a-z]来表示字母范围的方式可以编写简写版本。</SP< span>

  1. string str1 = "THE quick BROWN fox JUMPED over THE lazy DOG";
  2. MatchCollection matchSet;
  3. matchSet = Regex.Matches(str1, "[a-z]");
  4. foreach (Match aMatch in matchSet)
  5. Console.WriteLine("Matches at: " + aMatch);

 

5.4.断言修改正则表达式

 

1.^

C#语言包含一系列可以添加给正则表达式的运算符。这些运算符可以在不导致正则表达式引擎遍历字符串的情况下改变表达式的行为。这些运算符被称为断言。

第一个要研究的断言会导致正则表达式只能在字符串或行的开始处找到匹配。这个断言由脱字符号( ^)产生。

在下面这段程序中,正则表达式只与第一个字符为字母“ h”的字符串相匹配,而忽略掉字符串中其他位置上的“ h”。

  1. string[] words = new string[] { "heal", "heel", "noah", "techno" };
  2. string regExp = "^h";
  3. Match aMatch;
  4. foreach (string word in words)
  5. if (Regex.IsMatch(word, regExp))
  6. {
  7. aMatch = Regex.Match(word, regExp);
  8. Console.WriteLine("Matched: " + word + " at position: " + aMatch.Index);
  9. }

这段代码的输出就只有字符串“ heal”和“ heel”匹配。

 

2.$

这里还有一个断言会导致正则表达式只在行的末尾找到匹配。这个断言就是美元符号( $)。

string regExp = "h$";

那么“ noah”就是唯一能找到的匹配

 

3.\b

指定所有匹配只能发生在单词的边缘。这就意味着匹配只能发生在用空格分隔的单词的开始或结束处。此断言用\b 表示。

例子:查找以h或H开头的字符

  1. string words = "hark, what doth thou say, Harold? ";
  2. string regExp = @"(\bh|\bH)\w+";
  3. MatchCollection aMatch;
  4. if (Regex.IsMatch(words, regExp))
  5. {
  6. aMatch = Regex.Matches(words, regExp);
  7. foreach (Match item in aMatch)
  8. {
  9. Console.WriteLine("Matched: " + item + " at position: " + item.Index);
  10. }
  11.  
  12. }

 

5.5.分组构造

 

5.5.1 匿名组

"08/14/57 46 02/25/59 45 06/05/85 18 03/12/88 16 09/09/90 13"

这个字符串就是由生日和年龄组成的。如果只需要匹配年龄而不要生日,

  1. string words = "08/14/57 46 02/25/59 45 06/05/85 18 03/12/88 16 09/09/90 13";
  2. string regExp1 = @"(\s\d{2}\s|\s\d{2}\b)";
                MatchCollection matchSet = Regex.Matches(words, regExp1);
                foreach (Match aMatch in matchSet)
                    Console.WriteLine(aMatch.Groups[0].Captures[0]);

 

5.5.2 命名组

(?<ages>\s\d{2}\s|\s\d{2}\b)

 

5.5.3 零度正向和反向预搜索

 

5.5.3.1.正向预搜索断言

(?= reg-exp-char)

reg-exp-char 是正则表达式或元字符

只要搜索到匹配的当前子表达式在指定位置的右侧,那么匹配就继续。

  1. string strwords = "lions lion tigers tiger bears,bear";
  2. string regexp2 = @"\w+(?=\s)";
  3. MatchCollection matchSet1 = Regex.Matches(strwords, regexp2);
  4. foreach (Match aMatch in matchSet1)
  5. //Console.WriteLine(aMatch.Groups[0].Captures[0]);
  6. Console.WriteLine(aMatch.Captures[0]);

正则表达式匹配单词,但是不匹配空格。记住这一点是非常重要的。

 

5.5.3.2.负的正向预搜索断言

string words = "subroutine routine subprocedure procedure";

string regExp1 = \\b(?!sub)\\w+\\b;

 

5.5.3.3.反向预搜索断言

这些断言会正向左或反向左搜索,而不是向右了

  1. //这些断言会正向左或反向左搜索,而不是向右了
  2. string strwords3 = "subroutines routine subprocedures procedure";
  3. string regexp3 = @"\b\w+(?<=s)\b";
  4. MatchCollection matchSet3 = Regex.Matches(strwords3, regexp3);
  5. foreach (Match aMatch in matchSet3)
  6. //Console.WriteLine(aMatch.Groups[0].Captures[0]);
  7. Console.WriteLine(aMatch.Captures[0]);

匹配的单词有“ subroutines”和“ subprocedures”。

 

5.6.CaptureCollection类

当正则表达式匹配子表达式的时候,产生了一个被称为是 Capture 的对象,而且会把此对象添加到名为 CaptureCollection 的集合里面。当在正则表达式中使用命名组的时候,这个组就由自己的捕获集合。为了重新得到用了命名组的正则表达式所收集的捕获,就要调用来自 Match 对象 Group 属性的 Captures 属性。这在实例中是很容易理解的。

  1. string words4 = "08/14/57 46 02/25/59 45 06/05/85 18 03/12/88 16 09/09/90 13";
  2. string regExp4 = @"(?<dates>\d{2}/\d{2}/\d{2})(?<ages>\s\d{2}\s)";
  3. MatchCollection matchSet4 = Regex.Matches(words4, regExp4);
  4. foreach (Match item in matchSet4)
  5. {
  6. foreach (Capture ac in item.Groups["dates"].Captures)
  7. {
  8. Console.WriteLine("dates:" + ac.Value);
  9. }
  10. foreach (Capture ac in item.Groups["ages"].Captures)
  11. {
  12. Console.WriteLine("ages:" + ac.Value);
  13. }
  14. }

数据结构和算法 – 5.模式匹配和文本处理的更多相关文章

  1. 数据结构与算法 Big O 备忘录与现实

    不论今天的计算机技术变化,新技术的出现,所有都是来自数据结构与算法基础.我们需要温故而知新.        算法.架构.策略.机器学习之间的关系.在过往和技术人员交流时,很多人对算法和架构之间的关系感 ...

  2. 《数据结构与算法JavaScript描述》

    <数据结构与算法JavaScript描述> 基本信息 作者: (美)Michael McMillan 译者: 王群锋 杜欢 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:9 ...

  3. 数据结构与算法--Boyer-Moore和Rabin-Karp子字符串查找

    数据结构与算法--Boyer-Moore和Rabin-Karp子字符串查找 Boyer-Moore字符串查找算法 注意,<算法4>上将这个版本的实现称为Broyer-Moore算法,我看了 ...

  4. Android版数据结构与算法(七):赫夫曼树

    版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 近期忙着新版本的开发,此外正在回顾C语言,大部分时间没放在数据结构与算法的整理上,所以更新有点慢了,不过既然写了就肯定尽力将这部分完全整理好分享出 ...

  5. Python3-Cookbook总结 - 第一章:数据结构和算法

    第一章:数据结构和算法 Python 提供了大量的内置数据结构,包括列表,集合以及字典.大多数情况下使用这些数据结构是很简单的. 但是,我们也会经常碰到到诸如查询,排序和过滤等等这些普遍存在的问题. ...

  6. 数据结构与算法JS实现

      行解算法题,没错,就是这么方便. 当然也可以使用 Node.js 环境来执行,具体参考Node.js官方文档即可. 二 对象和面向对象编程 js中5种数据类型,并没有定义更多的数据类型,但是运用j ...

  7. 数据结构 Sunday算法

    Sunday算法是Daniel M.Sunday于1990年提出的字符串模式匹配算法.相对比较KMP和BM算法而言,简单了许多. Sunday算法的思想类似于BM算法中的坏字符思想,有点像其删减版.差 ...

  8. Python(一)数据结构和算法的20个练习题问答

    数据结构和算法 Python 提供了大量的内置数据结构,包括列表,集合以及字典.大多数情况下使用这些数据结构是很简单的. 但是,我们也会经常碰到到诸如查询,排序和过滤等等这些普遍存在的问题. 因此,这 ...

  9. 为什么我要放弃javaScript数据结构与算法(第一章)—— JavaScript简介

    数据结构与算法一直是我算比较薄弱的地方,希望通过阅读<javaScript数据结构与算法>可以有所改变,我相信接下来的记录不单单对于我自己有帮助,也可以帮助到一些这方面的小白,接下来让我们 ...

随机推荐

  1. 在应用中嵌入Python:转

    在应用中嵌入Python 前面的章节讨论如何扩展Python,如何生成适合的C库等.不过还有另一种情况:通过将Python嵌入C/C++应用以扩展程序的功能.Python嵌入实现了一些使用Python ...

  2. Cocos2d-x 3.0 Json用法 Cocos2d-x xml解析

    Cocos2d-x 3.0 加入了rapidjson库用于json解析.位于external/json下. rapidjson 项目地址:http://code.google.com/p/rapidj ...

  3. 符瑞艺 160809228_C语言程序设计实验2 选择结构程序设计

    实验2- 输入3个数,并按由大到小的顺序输出. 实验要求: 编写一个C程序,输入3个数,并按由大到小的顺序输出. 参考: 源码: #include <stdio.h> int main() ...

  4. Android四种基本布局(LinearLayout \ RelativeLayout \ FrameLayout \ TableLayout)

    ------------------------------------------LinearLayout---------------------------------------------- ...

  5. 转: Annovar 软件注释流程介绍

    第一步:下载Annovar 上Annovar官网下载(http://annovar.openbioinformatics.org/en/latest/user-guide/download/),现在要 ...

  6. Python自动化之rabbitmq rpc client端代码分析(原创)

    RPC调用client端解析 import pika import uuid # 建立连接 class FibonacciRpcClient(object): def __init__(self): ...

  7. phpcms不显示验证码

    只需修改./caches/configs/system.php即可 1.本地域名如果是 http://localhost 如果所有的文件都在根目录下(例如apache下的htdocs或www),此时, ...

  8. 查找问题的利器 - Git Bisect

    原文:http://gitbook.liuhui998.com/5_4.html 假设你在项目的'2.6.18'版上面工作, 但是你当前的代码(master)崩溃(crash)了. 有时解决这种问题的 ...

  9. Largest BST Subtree

    Given a binary tree, find the largest subtree which is a Binary Search Tree (BST), where largest mea ...

  10. 【leetcode】N-Queens II

    N-Queens II Follow up for N-Queens problem. Now, instead outputting board configurations, return the ...