.NET进阶学习;.NET学习;C#: C#教程(四十一)正则表达式(1)

2009年5月1日星期五

.NET进阶学习;.NET学习;C#: C#教程(四十一)正则表达式(1)


许多您都不太熟悉正则表达式语言所以本节将主要解释正则表达式和相关的.NET类如果您很熟悉正则表达式就可以跳过本节学习.NET基类的引用注意.NET正则表达式引擎是为兼容Perl5的正则表达式设计的但有一些新特性

8.2.1正则表达式概述
正则表达式语言是一种专门用于字符串处理的语言它包含两个功能

一组用于标识字符类型的转义代码您可能很熟悉DOS表达式中的*字符表示任意子字符串(例如DOS命令DirRe*会列出所有名称以Re开头的文件)正则表达式使用与*类似的许多序列来表示任意一个字符一个单词一个可选的字符等

一个系统在搜索操作中它把子字符串和中间结果的各个部分组合起来

使用正则表达式可以对字符串执行许多复杂而高级的操作例如

区分(可以是标记或删除)字符串中所有重复的单词例如把Thecomputerbooksbooks转换为Thecomputerbooks

把所有单词都转换为标题格式例如把thisisaTitle转换为ThisIsATitle

把长于3个字符的所有单词都转换为标题格式例如把thisisaTitle转换为ThisisaTitle

确保句子有正确的大写形式

区分URI的各个元素(例如http://www.wrox.com提取出协议计算机名文件名等)

当然这些都是可以在C#中用System.String和System.Text.StringBuilder执行的任务但是在一些情况下还需要编写相当多的C#代码如果使用正则表达式这些代码一般可以压缩为几行代码实际上是实例化了一个对象System.Text.RegularExpressions.RegEx(甚至更简单调用静态的RegEx()方法)给它传送要处理的字符串和一个正则表达式(这是一个字符串包含用正则表达式语言编写的指令)就可以了

正则表达式字符串初看起来像是一般的字符串但其中包含了转义序列和有特定含义的其他字符例如序列\b表示一个字的开头和结尾(字的边界)如果要表示正在查找以字符th开头的字就可以编写正则表达式\bth(即序列字边界是th)如果要搜索所有以th结尾的字就可以编写th\b(序列th字边界)但是正则表达式要比这复杂得多例如可以在搜索操作中找到存储部分文本的工具性程序本节仅介绍正则表达式的功能

假定应用程序需要把US电话号码转换为国际格式在美国电话号码的格式为314-123-1234常常写作(314)123-1234在把这个国家格式转换为国际格式时必须在电话号码的前面加上+1(美国的国家代码)并给区域代码加上括号+1(314)123-1234在查找和替换时这并不复杂但如果要使用字符串类完成这个转换就需要编写一些代码(这表示必须使用System.String上的方法来编写代码)而正则表达式语言可以构造一个短的字符串来表达上述含义

所以本节只有一个非常简单的示例我们只考虑如何查找字符串中的某些子字符串无须考虑如何修改它们

8.2.2RegularExpressionsPlayaround示例
下面将开发一个小示例执行并显示一些搜索的结果说明正则表达式的一些特性以及如何在C#中使用.NET正则表达式引擎这个示例文档中使用的文本是引自另一本有关XML的WroxPress书(ASP.NET1.1高级编程清华大学出版社翻译出版)

stringText=

@"Thiscomprehensivecompendiumprovidesabroadandthoroughinvestigationofall

aspectsofprogrammingwithASP.NET.Entirelyrevisedandupdatedforthe1.1

ReleaSEOf.NET,thisbookwillgiveyoutheinformationyouneedtomasterASP.NET

andbuildadynamic,successful,enterpriseWebapplication.";

注意

不考虑换行则上面的表达式是合法的C#代码说明了使用字符串时应在前面加上符号@

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

stringPattern="ion";

MatchCollectionMatches=Regex.Matches(Text,Pattern,

RegexOptions.IgnoreCase|

RegexOptions.ExplicitCapture);

foreach(MatchNextMatchinMatches)

{

Console.WriteLine(NextMatch.Index);

}

在这段代码中使用了System.Text.RegularExpressions命名空间中Regex类的静态方法Matches()这个方法的参数是一些输入文本一个模式和RegexOptions枚举中的一组可选标志在本例中指定所有的搜索都不应区分大小写另一个标记ExplicitCapture改变了收集匹配的方式对于本例这样可以使搜索的效率更高其原因详见后面的内容(尽管它还有这里没有介绍的其他用法)Matches()返回MatchCollections对象的引用匹配是一个技术术语表示表达式中模式实例的查找结果用System.Text.RegularExpressions.Match来代表因此我们返回一个包含所有匹配的MatchCollection每个匹配都用一个Match对象来表示在上面的代码中只是在集合中迭代使用Match类的Index属性返回输入文本中匹配所在的索引运行这段代码将得到3个匹配

除了一些新的.NET基类外这些内容都不是新的但正则表达式的功能主要取决于模式字符串原因是模式字符串不仅仅包含纯文本如前所述它还可以包含元字符和转义序列其中元字符是给出命令的特定字符而转义序列的工作方式与C#的转义序列相同它们都是以反斜杠\开头的字符具有特殊的含义

例如假定要查找以n开头的字就可以使用转义序列\b它表示一个字的边界(字的边界是以某个字母数字表的字符开头或者后面是一个空白字符或标点符号)可以编写如下代码

stringPattern=@"\bn";

MatchCollectionMatches=Regex.Matches(Text,Pattern,

RegexOptions.IgnoreCase|

RegexOptions.ExplicitCapture);

注意字符串前面的符号@要在运行时把\b传递给.NET正则表达式引擎反斜杠\不应被C#编译器解释为转义序列如果要查找以序列ion结尾的字可以使用下面的代码

stringPattern=@"ion\b";

如果要查找以字母a开头以序列ion结尾的所有字(在本例中仅有一个匹配application)就必须在上面的代码中添加一些内容显然我们需要一个以\ba开头以ion\b结尾的模式但中间的内容怎么办需要告诉应用程序在a和ion中间的内容可以是任意长度的任意字符只要这些字符不是空白即可实际上正确的模式如下所示

stringPattern=@"\ba\S*ion\b";

使用正则表达式要习惯的一点是对像这样怪异的字符序列见怪不怪但这个序列的工作是非常逻辑化的转义序列\S表示任何不是空白的字符*称为数量词其含义是前面的字符可以重复任意次包括0次序列\S*表示任意个不是空白的字符因此上面的模式匹配于以a开头以ion结尾的任何单词

表8-4是可以使用的一些主要的特定字符或转义序列但这个表并不完整要查看完整的列表请参考MSDN文档

表8-4

符号
含义
示例
匹配的示例

^
输入文本的开头
^B
B但只能是文本中的第一个字符

$
输入文本的结尾
X$
X但只能是文本中的最后一个字符

.
除了换行字符(\n)以外的所有单个字符
i.ation
isationization

*
可以重复0次或多次的前导字符
ra*t
rtratraat和raaat等




(续表)

+
可以重复1次或多次的前导字符
ra+t
ratraat和raaat等(但不能是rt)

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

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

\S
任何不是空白的字符
\SF
aFrFcF但不能是\tf

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

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




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

0 评论:

发表评论