专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »DotNet » 正则表达式字符串:C#利用正则表达式实现字符串搜索 »正文

正则表达式字符串:C#利用正则表达式实现字符串搜索

来源: 发布时间:星期四, 2009年2月12日 浏览:148次 评论:0


 1、正则表达式介绍

  正则表达式提供了功能强大、灵活而又高效思路方法来处理文本正则表达式全面模式匹配表示法可以快速地分析大量文本以找到特定模式;提取、编辑、替换或删除文本子串;或将提取串添加到集合以生成报告对于处理串(例如 HTML 处理、日志文件分析和 HTTP 标头分析)许多应用而言正则表达式是不可缺少工具

  .NET 框架正则表达式并入了其他正则表达式实现最常见功能被设计为和 Perl 5 正则表达式兼容.NET 框架正则表达式还包括些在其他实现中尚未提供功能.NET 框架正则表达式类是基类库部分并且可以和面向公共语言运行库任何语言或工具起使用

  2、串搜索

  正则表达式语言由两种基本类型组成:原义(正常)文本和元正是元组为正则表达式提供了处理能力当前所有文本编辑器都有些搜索功能通常可以打开个对话框在其中个文本框中键入要定位如果还要同时进行替换操作可以键入个替换比如在Windows操作系统中记事本、Office系列中文档编辑器都有这种功能这种搜索最简单方式这类问题很容易用String类String.Replace思路方法来解决但如果需要在文档中识别某个重复该如何办?编写个例程个String类中选择重复字是比较复杂此时使用语言就很适合

  般表达式语言是种可以编写搜索表达式语言在该语言中可以把文档中要搜索文本、转义序列和特定含义其他组合在例如序列\b表示个字开头和结尾(子边界)如果要表示正在查找th开头就可以编写般表达式\bth(即序列界是-t-h)如果要搜索所有以th结尾就可以编写th\b(序列t-h-字边界)但是般表达式要比这复杂得多例如可以在搜索操作中找到存储部分文本工具性(facility)
  3、.NET 框架正则表达式类

  下面通过介绍 .NET 框架正则表达式类熟悉下.NET框架下正则表达式使用思路方法

  3.1 Regex 类表示只读正则表达式

  Regex 类包含各种静态思路方法允许在不显式例子化其他类对象情况下使用其他正则表达式类以下代码举例创建了 Regex 类例子并在化对象时定义个简单正则表达式请注意使用了附加反斜杠作为转义它将 \s 匹配类中反斜杠指定为原义

  

  Regex r; // 声明个 Regex类变量

  r = Regex("\\s2000"); // 定义表达式

  3.2 Match 类表示正则表达式匹配操作结果

  以下举例使用 Regex 类 Match 思路方法返回 Match 类型对象以便找到输入串中第个匹配此举例使用 Match 类 Match.Success 属性来指示是否已找到匹配

  

  Regex r = Regex("abc"); // 定义个Regex对象例子

  Match m = r.Match("123abc456"); // 在串中匹配

   (m.Success)

  {

   Console.WriteLine("Found match at position " + m.Index); //输入匹配位置

  }

  3.3 MatchCollection 类表示非重叠匹配序列

  该集合为只读并且没有公共构造MatchCollection 例子是由 Regex.Matches 属性返回使用 Regex 类 Matches 思路方法通过在输入串中找到所有匹配填充 MatchCollection下面代码举例演示了如何将集合复制到(保留每匹配)和个整数(指示每匹配位置)中

  

  MatchCollection mc;

  String results = String[20];

   matchposition = [20];

  Regex r = Regex("abc"); //定义个Regex对象例子

  mc = r.Matches("123abc4abcd");

  for ( i = 0; i < mc.Count; i) //在输入串中找到所有匹配

  {

   results[i] = mc[i].Value; //将匹配串添在

   matchposition[i] = mc[i].Index; //记录匹配位置

  }

  3.4 GroupCollection 类表示捕获集合

  该集合为只读并且没有公共构造GroupCollection 例子在 Match.Groups 属性返回集合中返回下面控制台应用查找并输出由正则表达式捕获数目

  

  using ;

  using .Text.RegularExpressions;

  public RegexTest

  {

   public void RunTest

   {

    Regex r = Regex("(a(b))c"); //定义组

    Match m = r.Match("abdabc");

    Console.WriteLine("Number of groups found = " + m.Groups.Count);

   }

   public void Main

   {

    RunTest;

   }

  }

  该举例产生下面输出:

  

  Number of groups found = 3

  3.5 CaptureCollection 类表示捕获序列

  由于限定符捕获组可以在单个匹配中捕获多个Captures属性(CaptureCollection 类对象)是作为 Match 和 group 类成员提供以便于对捕获集合访问例如如果使用正则表达式 ((a(b))c)+(其中 + 限定符指定个或多个匹配)从串"abcabcabc"中捕获匹配则子匹配 Group CaptureCollection 将包含 3个成员
下面使用正则表达式 (Abc)+来查找串"XYZAbcAbcAbcXYZAbcAb"中个或多个匹配阐释了使用 Captures 属性来返回多组捕获



  

  using ;

  using .Text.RegularExpressions;

  public RegexTest

  {

   public void RunTest

   {

     counter;

    Match m;

    CaptureCollection cc;

    GroupCollection gc;

    Regex r = Regex("(Abc)+"); //查找"Abc"

    m = r.Match("XYZAbcAbcAbcXYZAbcAb"); //设定要查找

    gc = m.Groups;

    //输出查找组数目

    Console.WriteLine("Captured groups = " + gc.Count.);

    // Loop through each group.

    for ( i=0; i < gc.Count; i) //查找每个组

    {

     cc = gc[i].Captures;

     counter = cc.Count;

     Console.WriteLine("Captures count = " + counter.);

     for ( ii = 0; ii < counter; ii)

     {

      // Pr capture and position.

      Console.WriteLine(cc[ii] + " Starts at character " +

      cc[ii].Index); //输入捕获位置

     }

    }

   }

   public void Main {

    RunTest;

   }

  }

  此例返回下面输出结果:

  

  Captured groups = 2

  Captures count = 1

  AbcAbcAbc Starts at character 3

  Captures count = 3

  Abc Starts at character 3

  Abc Starts at character 6

  Abc Starts at character 9

  3.6 Capture 类包含来自单个子表达式捕获结果

  在 Group 集合中循环从 Group 成员中提取 Capture 集合并且将变量 posn 和 length 分别分配给找到每串中位置以及每长度

  

  Regex r;

  Match m;

  CaptureCollection cc;

   posn, length;

  r = Regex("(abc)*");

  m = r.Match("bcabcabc");

  for ( i=0; m.Groups[i].Value != ""; i)

  {

   cc = m.Groups[i].Captures;

   for ( j = 0; j < cc.Count; j)

   {

    posn = cc[j].Index; //捕获对象位置

    length = cc[j].Length; //捕获对象长度

   }

  }

  


  



  


  把组合组合起来后每次都会返回个组对象就可能并不是我们希望结果如果希望把组合作为搜索模式部分就会有相当大系统开销对于单个可以用以序列"?:"开头组禁止这么做就像URI样例那样而对于所有可以在RegEx.Matches思路方法上指定RegExOptions.ExplicitCapture标志

 4、利用正则表达式实现串搜索

  4.1 在C#中使用.NET般表达式引擎

  下面将通过个样例开发执行并显示些搜索结果介绍说明般表达式些特性以及如何在C#中使用.NET般表达式引擎介绍说明使用串时应在前面加上符号@

  

  String Text=@"I can not find my position in Beijing";

  把这个文本称为输入为了介绍说明般表达式.NET类本文先进行次纯文本搜索这次搜索不带任何转义序列或般表达式命令假定要查找所有串ion把这个搜索串称为模式使用般表达式和上面声明变量Text编写出下面代码:

  

  String Pattern = "ion";

  MatchCollection Matches = Regex.Matches(Text,Pattern,RegexOptions);

  foreach(Match NextMatch in Matches)

  { Console.WriteLine(NextMatch.Index); }

  在这段代码中使用了.Text.RegularExpressions名称空间中Regex类静态思路方法Match这个思路方法参数是些输入文本、个模式和RegexOptions每句中组可选标志Matches返回MatchCollection每个匹配都用个Match对象来表示在上面代码中只是在集合中迭代使用Match类Index属性返回输入文本中匹配所在索引运行这段代码将得到1个匹配项

  般集合功能主要取决于模式原因是模式串不仅仅包含纯文本如前所述还包含元和转义序列是给出命令特殊而转义序列工作方式和C#转义序列相同它们都是以反斜杠\开头具有特殊含义例如假定要查找以n开头就可以使用转义序列\b它表示个字边界(字边界是以某个字母数字标开头或者后面是个空白或标点符号)下面编写如下代码:

  

  String Pattern = @"\bn";

  MatchCollection Matches = Regex.Matches(Text,Pattern,RegexOptions.IgnoreCase 

  RegexOptions.ExplicitCapture);

  要在运行时把\b传递给.NET般表达式引擎反斜杠\不应被C#编译器解释为转义序列如果要查找以序列ion结尾可以使用下面代码:

  

  String Pattern = @"ion\b";

  如果要查找以字母n开头以序列ion结尾所有字需要个以\bn开头以ion\b结尾模式中间内容如何办?需要告诉计算机n和ion中间内容可以是任意长度只要不是空白即可正确模式如下所示:



  

  String Pattern = @"\bn\S*ion\b";

  4.2 特定或转义序列

  大多数重要正则表达式语言运算符都是非转义单个转义符 \(单个反斜杠)通知正则表达式分析器反斜杠后面不是运算符例如分析器将星号 (*) 视为重复限定符而将后跟星号反斜杠 (\*) 视为 Unicode 002A

  使用般表达式要习惯点是查看像这样怪异序列但这个序列工作是非常逻辑化转义序列\S表示任何不适空白*称为数量词其含义是前面可以重复任意次包括0次序列\S*表示任何不适空白因此上面模式匹配于以n开头以ion结尾任何单个字下表中列出转义在正则表达式和替换模式中都会被识别

 表1:特定或转义序列

  

  特定或转义序列 含义 样例 匹配样例

  ^ 输入文本开头 ^B B但只能是文本中

  $ 输入文本结尾 X$ X但只能是文本中最后

  . 除了换行(\n)以外所有单个 i.ation isation、ization

  * 可以重复0次或多次前导 ra*t rat、raat等

  + 可以重复1次或多次前导 ra+t rt、rat、raat等

  ? 可以重复0次或1次前导 ra?t 只有rt和rat匹配

  \s 任何空白 \sa [space]a,\ta,\na(\t和\n和C#\t和\n含义相同)

  \S 任何不是空白 \SF aF,rF,cF但不能是\tf

  \b 字边界 ion\b 以ion结尾任何字

  \B 不是字边界位置 \BX\B 字中间任何X

  如果要搜索个元也可以通过带有反斜杠转义来表示例如.表示除了换行以外任何而\.表示个点

  可以把可替换放在方括号中请求匹配包含这些例如[1 c]表示可以是1或者是c如果要搜索map或者man可以使用序列"ma[n p]"(仅指引号内下面雷同)在方括号中也可以制定个范围例如"[a-z]"表示所有小写字母(使用连字号 (-) 允许指定连续范围)"[B-F]"表示B到F的间所有大写字母"[0-9]"表示个数字如果要搜索个整数(该序列只包含0到9)就可以编写"[0-9]+"(注意使用+表示至少要有这样个数字但可以有多个数字所以9、83和3443等都是匹配)

  下面看看般表达式结果编写个例子RegularExpressionsZzy建立几个般表达式显示其结果让用户了解下表达式是如何工作

  该例子核心是个思路方法WriteMatches它把MatchCollection中所有匹配以比较详细方式显示出来对于每个匹配它都会显示该匹配在输入串中所在索引匹配串和个略长其中包含输入文本中至多8个外围其中至少有5个放在匹配前面至多5个放在匹配后面(如果匹配位置在输入文本开头或结尾5个则结果中匹配前后就会少于4个)换言的靠近输入文本末尾匹配应是"and messaging ofd"匹配前后各有5个但位于输入文本最后个字上匹配就应是"g of data"匹配字后只有在该后面是结尾这个长串可以更清楚地表明般表达式是在什么地方查找到匹配:

  

   void WriteMatches( text, MatchCollection matches)

  {

   Console.WriteLine("Original text was: \n\n" + text + "\n");

   Console.WriteLine("No. of matches: " + matches.Count);

   foreach (Match nextMatch in matches)

   {

     Index = nextMatch.Index;

     result = nextMatch.;

     charsBefore = (Index < 5) ? Index : 5;

     fromEnd = text.Length - Index - result.Length;

     charsAfter = (fromEnd < 5) ? fromEnd : 5;

     charsToDisplay = charsBefore + charsAfter + result.Length;

    Console.WriteLine("Index: {0}, \tString: {1}, \t{2}",Index, result,

    text.Sub(Index - charsBefore, charsToDisplay));

   }

  }

  在这个思路方法中处理过程是确定在较长串中有多少个可以显示而无需超限输入文本开头或结尾注意在Match对象上使用了另个属性Value它包含标识该匹配而且RegularExpressionsZzy只包含名为Find_poFind_n等思路方法这些思路方法根据本文执行某些搜索操作

  4.3 正则表达式选项

  可以使用影响匹配行为选项修改正则表达式模式可以通过两种基本思路方法设置正则表达式选项:其是可以在 Regex(pattern, options) 构造 options 参数中指定其中 options 是 RegexOptions 枚举值按位"或"组合;其 2是使用内联 (?imnsx-imnsx:) 分组构造或 (?imnsx-imnsx) 其他构造在正则表达式模式内设置它们

  在内联选项构造中个选项或组选项前面减号 (-) 用于关闭这些选项例如内联构造 (?ix-ms) 将打开 IgnoreCase 和 IgnorePatternWhiteSpace 选项而关闭 Multiline 和 Singleline 选项

  表2:RegexOptions 枚举成员以及等效内联选项

  

  RegexOption 成员 内联 介绍说明

  None 无 指定不设置任何选项

  IgnoreCase i 指定不区分大小写匹配

  Multiline m 指定多行模式更改 ^ 和 $ 含义以使它们分别和任何行开头和结尾匹配而不只是和整个开头和结尾匹配

  ExplicitCapture n 指定唯有效捕获是显式命名或编号 (?...) 形式这允许圆括号充当非捕获组从而避免了由 (?:...) 导致语法上笨拙



  Compiled 无 指定正则表达式将被编译为生成该正则表达式 Microsoft 中间语言 (MSIL) 代码;以较长启动时间为代价得到更快执行速度

  Singleline s 指定单行模式更改句点 (.) 含义以使它和每个(而不是除 \n 外所有)匹配

  IgnorePatternWhitespace x 指定从模式中排除非转义空白并启用数号 (#) 后面注释请注意空白永远不会从类中消除

  RightToLeft 无 指定搜索是从右向左而不是从左向右进行具有此选项正则表达式将移动到起始位置左边而不是右边(因此起始位置应指定为结尾而不是开头)为了避免构造具有无限循环正则表达式可能性此选项不能在中流指定但是(?<) 回顾后发构造提供了可用作子表达式类似替代物


  例如Find_po在字开头处查找以"po"开头串:

  

   void Find_po

  {

    text = @" I can not find my position in Beijing ";

    pattern = @"\bpo\S*ion\b";

   MatchCollection matches = Regex.Matches(text, pattern, RegexOptions.IgnoreCase

    RegexOptions.IgnorePatternWhitespace   RegexOptions.ExplicitCapture);

   WriteMatches(text, matches);

  }

  这段代码还使用了名称空间RegularExpressions:

  

  using ;

  using .Text.RegularExpressions;

  4.4 匹配、组和捕获

  般表达式个很好特性是可以把组合起来方式和C#中复合语句在C#中可以通过把任意数量语句放在花括号中方式把它们组合在其结果就像个复合语句那样般表达式模式中也可以把任何组合起来(包括元和转义序列)像处理那样处理它们区别是要使用圆括号而不是花括号得到序列成为个组

  例如模式"(an)+"定位序列an任以重复量词+只应用于它前面我们把组合起来了所以它现在把重复an作为个单元来对待"(an)."应用到输入文本"bananas came to Europe late in the annals of history"上会从bananas中选择出anan方面如果使用an+则将从annals中选择ann从bananas中选择出两个an为什么(an)+选择是anan而没有把单个an作为个匹配匹配规则是不能重复如果有可能重复在默认情况下就选择较长匹配

  但是功能要比这强大得多在默认情况下把模式部分组合为个组时就要求般表达式引擎记住可以按照这个组来匹配也可以按照整个模式来匹配换言的可以把组当作个要匹配模式如果要把串分解为各个部分这种模式就是非常有效
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: