正则表达式构造与测试小工具(上)

前言


最初接触到正则表达式是在大一时准备高程考试的时候,那时候只知道这个东西可以拿来对对给定的语句进行匹配,可对它很多的东西都不了解。在学习了C#后,终于有机会接触到这方面的细节了,其实我用过的方面也不多,回想起来也就有几个地方用过:比如用户注册时判断email地址是否合法,手机号码,身份证号码是否符合格式,用户名和密码的限制等,再有就是在做一些文本的搜索与替换,当然字符串处理的很多方面都会用到。

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

我们可能比较熟悉在 DOS 文件系统中使用的 ? 和 * 元字符,这两个元字符分别代表任意单个字符和字符组。DOS 文件命令 COPY *.DOC A: 命令文件系统将文件扩展名为 .DOC 的所有文件均复制到 A 驱动器的磁盘中。元字符 * 代表文件扩展名 .DOC 前的任何文件名。

以下简单介绍下 .NET Framework 中用到的正则表达式类。

Regex

Regex 类表示不可变(只读)正则表达式类。它还包含各种静态方法,允许在不显式创建其他类的实例的情况下使用其他正则表达式类。

以下代码示例创建了 Regex 类的实例并在初始化对象时定义一个简单的正则表达式。请注意,使用了附加的反斜杠作为转义字符,它将 /s 匹配字符类中的反斜杠指定为原义字符。

None.gif // DeclareobjectvariableoftypeRegex.
None.gif

None.gifRegexr;
None.gif
None.gif
// CreateaRegexobjectanddefineitsregularexpression.
None.gif

None.gifr
= new Regex( " //s2000 " );
None.gif
None.gif

Match

Match 类表示正则表达式匹配操作的结果。以下示例使用 Regex 类的 Match 方法返回 Match 类型的对象,以便找到输入字符串中的第一个匹配项。此示例使用 Match 类的 Match.Success 属性来指示是否已找到匹配。

None.gif // CreateanewRegexobject.
None.gif

None.gifRegexr
= new Regex( " abc " );
None.gif
None.gif
// Findasinglematchinthestring.
None.gif

None.gifMatchm
= r.Match( " 123abc456 " );
None.gif
None.gif
if (m.Success)
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif
//Printoutthecharacterpositionwhereamatchwasfound.
InBlock.gif
InBlock.gif
//(Characterposition3inthiscase.)
InBlock.gif

InBlock.gifConsole.WriteLine(
"Foundmatchatposition"+m.Index);
InBlock.gif
ExpandedBlockEnd.gif}

None.gif
None.gif

MatchCollection

MatchCollection 类表示成功的非重叠匹配的序列。该集合为不可变(只读)的,并且没有公共构造函数。MatchCollection 的实例是由 Regex.Matches 属性返回的。

以下示例使用 Regex 类的 Matches 方法,通过在输入字符串中找到的所有匹配填充 MatchCollection。该示例将此集合复制到一个字符串数组和一个整数数组中,其中字符串数组用以保存每个匹配项,整数数组用以指示每个匹配项的位置。

None.gif MatchCollectionmc;
None.gif
None.gifString[]results
= new String[ 20 ];
None.gif
None.gif
int []matchposition = new int [ 20 ];
None.gif
None.gif
None.gif
None.gif
// CreateanewRegexobjectanddefinetheregularexpression.
None.gif

None.gifRegexr
= new Regex( " abc " );
None.gif
None.gif
// UsetheMatchesmethodtofindallmatchesintheinputstring.
None.gif

None.gifmc
= r.Matches( " 123abc4abcd " );
None.gif
None.gif
// Loopthroughthematchcollectiontoretrieveall
None.gif
None.gif
// matchesandpositions.
None.gif

None.gif
for ( int i = 0 ;i < mc.Count;i ++ )
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif
//Addthematchstringtothestringarray.
InBlock.gif

InBlock.gifresults[i]
=mc[i].Value;
InBlock.gif
InBlock.gif
//Recordthecharacterpositionwherethematchwasfound.
InBlock.gif

InBlock.gifmatchposition[i]
=mc[i].Index;
InBlock.gif
ExpandedBlockEnd.gif}

None.gif
None.gif

GroupCollection

GroupCollection 类表示捕获的组的集合并返回单个匹配中捕获的组的集合。该集合为不可变(只读)的,并且没有公共构造函数。GroupCollection 的实例在 Match.Groups 属性返回的集合中返回。

以下控制台应用程序示例查找并输出由正则表达式捕获的组的数目。有关如何提取组集合的每一成员中的各个捕获项的示例,请参见下面一节的 Capture Collection 示例。

None.gif using System;
None.gif
None.gif
using System.Text.RegularExpressions;
None.gif
None.gif
None.gif
None.gif
public class RegexTest
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif
publicstaticvoidRunTest()
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
InBlock.gif
//Definegroups"abc","ab",and"b".
InBlock.gif

InBlock.gifRegexr
=newRegex("(a(b))c");
InBlock.gif
InBlock.gifMatchm
=r.Match("abdabc");
InBlock.gif
InBlock.gifConsole.WriteLine(
"Numberofgroupsfound="+m.Groups.Count);
InBlock.gif
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
publicstaticvoidMain()
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
InBlock.gifRunTest();
InBlock.gif
ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedBlockEnd.gif}

None.gif

该示例产生下面的输出。

None.gif Numberofgroupsfound = 3
None.gif

CaptureCollection

CaptureCollection 类表示捕获的子字符串的序列,并且返回由单个捕获组执行的捕获的集合。由于限定符,捕获组可以在单个匹配中捕获多个字符串。Captures 属性(CaptureCollection 类的对象)是作为 Match 和 group 类的成员提供的,以便于对捕获的子字符串的集合的访问。

例如,如果使用正则表达式 ((a(b))c)+(其中 + 限定符指定一个或多个匹配)从字符串“abcabcabc”中捕获匹配,则子字符串的每一匹配的 Group 的 CaptureCollection 将包含三个成员。

以下控制台应用程序示例使用正则表达式 (Abc)+ 来查找字符串“XYZAbcAbcAbcXYZAbcAb”中的一个或多个匹配。该示例阐释了使用 Captures 属性来返回多组捕获的子字符串。

None.gif using System;
None.gif
None.gif
using System.Text.RegularExpressions;
None.gif
None.gif
None.gif
None.gif
public class RegexTest
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif
publicstaticvoidRunTest()
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
InBlock.gif
intcounter;
InBlock.gif
InBlock.gifMatchm;
InBlock.gif
InBlock.gifCaptureCollectioncc;
InBlock.gif
InBlock.gifGroupCollectiongc;
InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif
//Lookforgroupingsof"Abc".
InBlock.gif

InBlock.gifRegexr
=newRegex("(Abc)+");
InBlock.gif
InBlock.gif
//Definethestringtosearch.
InBlock.gif

InBlock.gifm
=r.Match("XYZAbcAbcAbcXYZAbcAb");
InBlock.gif
InBlock.gifgc
=m.Groups;
InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif
//Printthenumberofgroups.
InBlock.gif

InBlock.gifConsole.WriteLine(
"Capturedgroups="+gc.Count.ToString());
InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif
//Loopthrougheachgroup.
InBlock.gif

InBlock.gif
for(inti=0;i<gc.Count;i++)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
InBlock.gifcc
=gc[i].Captures;
InBlock.gif
InBlock.gifcounter
=cc.Count;
InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif
//Printnumberofcapturesinthisgroup.
InBlock.gif

InBlock.gifConsole.WriteLine(
"Capturescount="+counter.ToString());
InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif
//Loopthrougheachcaptureingroup.
InBlock.gif

InBlock.gif
for(intii=0;ii<counter;ii++)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
InBlock.gif
//Printcaptureandposition.
InBlock.gif

InBlock.gifConsole.WriteLine(cc[ii]
+"Startsatcharacter"+
InBlock.gif
InBlock.gifcc[ii].Index);
InBlock.gif
ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedSubBlockEnd.gif}

InBlock.gif
InBlock.gif
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
publicstaticvoidMain()dot.gif{
InBlock.gif
InBlock.gifRunTest();
InBlock.gif
ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedBlockEnd.gif}

None.gif
None.gif

此示例返回下面的输出结果。

None.gif Capturedgroups = 2
None.gif
None.gifCapturescount
= 1
None.gif
None.gifAbcAbcAbcStartsatcharacter
3
None.gif
None.gifCapturescount
= 3
None.gif
None.gifAbcStartsatcharacter
3
None.gif
None.gifAbcStartsatcharacter
6
None.gif
None.gifAbcStartsatcharacter
9
None.gif
None.gif

Group

group 类表示来自单个捕获组的结果。因为 Group 可以在单个匹配中捕获零个、一个或更多的字符串(使用限定符),所以它包含 Capture 对象的集合。因为 Group 继承自 Capture,所以可以直接访问最后捕获的子字符串(Group 实例本身等价于 Captures 属性返回的集合的最后一项)。

Group 的实例是由 Match.Groups(groupnum) 属性返回的,或者在使用“(?<groupname>)”分组构造的情况下,是由 Match.Groups("groupname") 属性返回的。

以下代码示例使用嵌套的分组构造来将子字符串捕获到组中。

None.gif int []matchposition = new int [ 20 ];
None.gif
None.gifString[]results
= new String[ 20 ];
None.gif
None.gif
// Definesubstringsabc,ab,b.
None.gif

None.gifRegexr
= new Regex( " (a(b))c " );
None.gif
None.gifMatchm
= r.Match( " abdabc " );
None.gif
None.gif
for ( int i = 0 ;m.Groups[i].Value != "" ;i ++ )
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif
//Copygroupstostringarray.
InBlock.gif

InBlock.gifresults[i]
=m.Groups[i].Value;
InBlock.gif
InBlock.gif
//Recordcharacterposition.
InBlock.gif

InBlock.gifmatchposition[i]
=m.Groups[i].Index;
InBlock.gif
ExpandedBlockEnd.gif}

None.gif
None.gif

此示例返回下面的输出结果。

None.gif results[ 0 ] = " abc " matchposition[ 0 ] = 3
None.gif
None.gifresults[
1 ] = " ab " matchposition[ 1 ] = 3
None.gif
None.gifresults[
2 ] = " b " matchposition[ 2 ] = 4
None.gif
None.gif

以下代码示例使用命名的分组构造,从包含“DATANAME:VALUE”格式的数据的字符串中捕获子字符串,正则表达式通过冒号“:”拆分数据。

None.gif Regexr = new Regex( " ^(?<name>//w+):(?<value>//w+) " );
None.gif
None.gifMatchm
= r.Match( " Section1:119900 " );
None.gif
None.gif

此正则表达式返回下面的输出结果。

None.gif m.Groups[ " name " ].Value = " Section1 "
None.gif
None.gifm.Groups[
" value " ].Value = " 119900 "
None.gif
None.gif

Capture

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

以下示例在 Group 集合中循环,从 Group 的每一成员中提取 Capture 集合,并且将变量 posn 和 length 分别分配给找到每一字符串的初始字符串中的字符位置,以及每一字符串的长度。

None.gif Regexr;
None.gif
None.gifMatchm;
None.gif
None.gifCaptureCollectioncc;
None.gif
None.gif
int posn,length;
None.gif
None.gif
None.gif
None.gifr
= new Regex( " (abc)* " );
None.gif
None.gifm
= r.Match( " bcabcabc " );
None.gif
None.gif
for ( int i = 0 ;m.Groups[i].Value != "" ;i ++ )
None.gif
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
InBlock.gif
//CapturetheCollectionforGroup(i).
InBlock.gif

InBlock.gifcc
=m.Groups[i].Captures;
InBlock.gif
InBlock.gif
for(intj=0;j<cc.Count;j++)
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif
InBlock.gif
//PositionofCaptureobject.
InBlock.gif

InBlock.gifposn
=cc[j].Index;
InBlock.gif
InBlock.gif
//LengthofCaptureobject.
InBlock.gif

InBlock.giflength
=cc[j].Length;
InBlock.gif
ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedBlockEnd.gif}

None.gif
None.gif

在以前编程中用到正则表达式时,总是需要在代码中来对构造出的正则表达式进行测试,不断重复进行着构造—测试---修改---测试的麻烦工作,而项目文件过大时编译一次真不是件舒服的事情,我就想到自己做一个小工具用来构造和测试正则表达式,并且产生相应的代码,这样就可以直接用到项目中来了,从而避免这些烦人的工作了。因此我目标分为如下两部分:1)对构造的正则表达式进行测试,如果测试成功就产生相应的代码。2)通过一些GUI来自动构造正则表达式子(当然这部分我还不大熟)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值