正则表达式.docx
《正则表达式.docx》由会员分享,可在线阅读,更多相关《正则表达式.docx(20页珍藏版)》请在冰点文库上搜索。
正则表达式
多少年来,许多的编程语言和工具都包含对正则表达式的支持,.NET基础类库中包含有一个名字空间和一系列可以充分发挥规则表达式威力的类,而且它们也都与未来的Perl5中的规则表达式兼容。
此外,regexp类还能够完成一些其他的功能,例如从右至左的结合模式和表达式的编辑等。
在这篇文章中,我将简要地介绍System.Text.RegularExpression中的类和方法、一些字符串匹配和替换的例子以及组结构的详细情况,最后,还会介绍一些你可能会用到的常见的表达式。
应该掌握的基础知识
规则表达式的知识可能是不少编程人员“常学常忘”的知识之一。
在这篇文章中,我们将假定你已经掌握了规则表达式的用法,尤其是Perl5中表达式的用法。
.NET的regexp类是Perl5中表达式的一个超集,因此,从理论上说它将作为一个很好的起点。
我们还假设你具有了C#的语法和.NET架构的基本知识。
如果你没有规则表达式方面的知识,我建议你从Perl5的语法着手开始学习。
在规则表达式方面的权威书籍是由杰弗里•弗雷德尔编写的《掌握表达式》一书,对于希望深刻理解表达式的读者,我们强烈建议阅读这本书。
RegularExpression组合体
regexp规则类包含在System.Text.RegularExpressions.dll文件中,在对应用软件进行编译时你必须引用这个文件,例如:
cscr:
System.Text.RegularExpressions.dllfoo.cs
命令将创建foo.exe文件,它就引用了System.Text.RegularExpressions文件。
名字空间简介
在名字空间中仅仅包含着6个类和一个定义,它们是:
Capture:
包含一次匹配的结果;
CaptureCollection:
Capture的序列;
Group:
一次组记录的结果,由Capture继承而来;
Match:
一次表达式的匹配结果,由Group继承而来;
MatchCollection:
Match的一个序列;
MatchEvaluator:
执行替换操作时使用的代理;
Regex:
编译后的表达式的实例。
Regex类中还包含一些静态的方法:
Escape:
对字符串中的regex中的转义符进行转义;
IsMatch:
如果表达式在字符串中匹配,该方法返回一个布尔值;
返回Match的实例;
Matches:
返回一系列的Match的方法;
Replace:
用替换字符串替换匹配的表达式;
Split:
返回一系列由表达式决定的字符串;
Unescape:
不对字符串中的转义字符转义。
简单匹配
我们首先从使用Regex、Match类的简单表达式开始学习。
Matchm=Regex.Match("abracadabra","(a|b|r)+");
我们现在有了一个可以用于测试的Match类的实例,例如:
if(m.Success)...
如果想使用匹配的字符串,可以把它转换成一个字符串:
Console.WriteLine("Match="+m.ToString());
这个例子可以得到如下的输出:
Match=abra。
这就是匹配的字符串了。
字符串的替换
简单字符串的替换非常直观。
例如下面的语句:
strings=Regex.Replace("abracadabra","abra","zzzz");
它返回字符串zzzzcadzzzz,所有匹配的字符串都被替换成了zzzzz。
现在我们来看一个比较复杂的字符串替换的例子:
strings=Regex.Replace("abra",@"^\s*(.*?
)\s*$","$1");
这个语句返回字符串abra,其前导和后缀的空格都去掉了。
上面的模式对于删除任意字符串中的前导和后续空格都非常有用。
在C#中,我们还经常使用字母字符串,在一个字母字符串中,编译程序不把字符“\”作为转义字符处理。
在使用字符“\”指定转义字符时,@"..."是非常有用的。
另外值得一提的是$1在字符串替换方面的使用,它表明替换字符串只能包含被替换的字符串。
匹配引擎的细节
现在,我们通过一个组结构来理解一个稍微复杂的例子。
看下面的例子:
stringtext="abracadabra1abracadabra2abracadabra3";
stringpat=@"
(#第一个组的开始
abra#匹配字符串abra
(#第二个组的开始
cad#匹配字符串cad
)?
#第二个组结束(可选)
)#第一个组结束
+#匹配一次或多次
";
//利用x修饰符忽略注释
Regexr=newRegex(pat,"x");
//获得组号码的清单
int[]gnums=r.GetGroupNumbers();
//首次匹配
Matchm=r.Match(text);
while(m.Success)
{
//从组1开始
for(inti=1;i{Groupg=m.Group(gnums[i]);//获得这次匹配的组Console.WriteLine("Group"+gnums[i]+"=["+g.ToString()+"]");//计算这个组的起始位置和长度CaptureCollectioncc=g.Captures;for(intj=0;j{Capturec=cc[j];Console.WriteLine("Capture"+j+"=["+c.ToString()+"]Index="+c.Index+"Length="+c.Length);}}//下一个匹配m=m.NextMatch();}这个例子的输出如下所示:Group1=[abra]Capture0=[abracad]Index=0Length=7Capture1=[abra]Index=7Length=4Group2=[cad]Capture0=[cad]Index=4Length=3Group1=[abra]Capture0=[abracad]Index=12Length=7Capture1=[abra]Index=19Length=4Group2=[cad]Capture0=[cad]Index=16Length=3Group1=[abra]Capture0=[abracad]Index=24Length=7Capture1=[abra]Index=31Length=4Group2=[cad]Capture0=[cad]Index=28Length=3 我们首先从考查字符串pat开始,pat中包含有表达式。第一个capture是从第一个圆括号开始的,然后表达式将匹配到一个abra。第二个capture组从第二个圆括号开始,但第一个capture组还没有结束,这意味着第一个组匹配的结果是abracad,而第二个组的匹配结果仅仅是cad。因此如果通过使用?符号而使cad成为一项可选的匹配,匹配的结果就可能是abra或abracad。然后,第一个组就会结束,通过指定+符号要求表达式进行多次匹配。现在我们来看看匹配过程中发生的情况。首先,通过调用Regex的constructor方法建立表达式的一个实例,并在其中指定各种选项。在这个例子中,由于在表达式中有注释,因此选用了x选项,另外还使用了一些空格。打开x选项,表达式将会忽略注释和其中没有转义的空格。然后,取得表达式中定义的组的编号的清单。你当然可以显性地使用这些编号,在这里使用的是编程的方法。如果使用了命名的组,作为一种建立快速索引的途径这种方法也十分有效。接下来是完成第一次匹配。通过一个循环测试当前的匹配是否成功,接下来是从group1开始重复对组清单执行这一操作。在这个例子中没有使用group0的原因是group0是一个完全匹配的字符串,如果要通过收集全部匹配的字符串作为一个单一的字符串,就会用到group0了。我们跟踪每个group中的CaptureCollection。通常情况下每次匹配、每个group中只能有一个capture,但本例中的Group1则有两个capture:Capture0和Capture1。如果你仅需要Group1的ToString,就会只得到abra,当然它也会与abracad匹配。组中ToString的值就是其CaptureCollection中最后一个Capture的值,这正是我们所需要的。如果你希望整个过程在匹配abra后结束,就应该从表达式中删除+符号,让regex引擎知道我们只需要对表达式进行匹配。基于过程和基于表达式方法的比较 一般情况下,使用规则表达式的用户可以分为以下二大类:第一类用户尽量不使用规则表达式,而是使用过程来执行一些需要重复的操作;第二类用户则充分利用规则表达式处理引擎的功能和威力,而尽可能少地使用过程。对于我们大多数用户而言,最好的方案莫过于二者兼而用之了。我希望这篇文章能够说明.NET语言中regexp类的作用以及它在性能和复杂性之间的优、劣点。基于过程的模式 我们在编程中经常需要用到的一个功能是对字符串中的一部分进行匹配或其他一些对字符串处理,下面是一个对字符串中的单词进行匹配的例子:stringtext="thequickredfoxjumpedoverthelazybrowndog.";System.Console.WriteLine("text=["+text+"]");stringresult="";stringpattern=@"\w+|\W+";foreach(MatchminRegex.Matches(text,pattern)){//取得匹配的字符串stringx=m.ToString();//如果第一个字符是小写if(char.IsLower(x[0]))//变成大写x=char.ToUpper(x[0])+x.Substring(1,x.Length-1);//收集所有的字符result+=x;}System.Console.WriteLine("result=["+result+"]");正象上面的例子所示,我们使用了C#语言中的foreach语句处理每个匹配的字符,并完成相应的处理,在这个例子中,新创建了一个result字符串。这个例子的输出所下所示:text=[thequickredfoxjumpedoverthelazybrowndog.]result=[TheQuickRedFoxJumpedOverTheLazyBrownDog.]基于表达式的模式 完成上例中的功能的另一条途径是通过一个MatchEvaluator,新的代码如下所示:staticstringCapText(Matchm){//取得匹配的字符串stringx=m.ToString();//如果第一个字符是小写if(char.IsLower(x[0]))//转换为大写returnchar.ToUpper(x[0])+x.Substring(1,x.Length-1);returnx;}staticvoidMain(){stringtext="thequickredfoxjumpedoverthelazybrowndog.";System.Console.WriteLine("text=["+text+"]");stringpattern=@"\w+";stringresult=Regex.Replace(text,pattern,newMatchEvaluator(Test.CapText));System.Console.WriteLine("result=["+result+"]");}同时需要注意的是,由于仅仅需要对单词进行修改而无需对非单词进行修改,这个模式显得非常简单。介绍一下C#正则表达式语法的相关规则,包括字符的规则、字母文本的规则等等。希望本文能对大家了解C#正则表达式语法有所帮助。正则表达式通常包含字母文本(Literaltext)和元字符(metacharacter)字母文本指的是普通文本如"abcde"可匹配字符串中任何包含"abcde"的字符串。元字符则更加灵活运用通用的表达式匹配所有符合此表达式规律的字符串。C#正则表达式语法一、匹配单个字符[]——从中选择一个字符匹配中间支持的类型:单词字符([ae])、非单词字符([!?;@#$*])、字母范围([A-Z])、数字范围([0])eg.正则表达式可匹配字符串[ae]ffectaffect,effect(此例中"[ae]"为元字符,"ffect"为字母文本)注意:1.要在字符类中匹配连字符,那么把连字符号作为第一个字符列出即可。2.可以在单个正则表达式中包含多个字符类。eg.[01][0-9]:[0-5][0-9][ap]m可以用来匹配如12:59pm格式的所有时间^——排除某些字符(在[]中表此意,还可表示字符串的开头)eg.正则表达式可匹配字符串不可匹配字符串m[^a]tmet,mit,m&t……matC#正则表达式语法二、匹配特殊字符可以使用的特殊字符:\t——匹配制表符\r——匹配硬回车符\f——匹配换页符\n——匹配换行符描述表示字符类的元字符:.——匹配任何除了\n以外的字符(或者在单行模式中的任何字符)\w——匹配任何单词字符(任何字母或数字)\W——匹配任何非单词字符(除了字母和数字以外的任何字符)\s——匹配任何空白字符(包括空格、换行、制表符等)\S——匹配任何非空白字符(除了空格、换行、制表符等的任何字符)\d——匹配任何数字字符(0~9的数字)\D——匹配任何非数字字符(除了0~9以外的任何字符)表示字符串中字符位置:^——匹配字符串的开头(或者多行模式下行的开头)。$——匹配字符串的结尾,或者是字符串结尾“\n”之前的最后一个字符,或者是多行模式中的行结尾。\A——匹配字符串的开头(忽略多行模式)\Z——匹配字符串的结尾或字符串结尾“\n”之前的最后一个字符(忽略多行模式)。\z——匹配字符串的结尾。\G——匹配当前搜索开始的位置。\b——匹配单词的边界。\B——匹配单词的非边界。注意:1.句点字符(.)特别有用。可以用它来表示任何一个字符。eg.正则表达式可匹配字符串01.17.8401/17/84,01-17-84,011784,01.17.842.可以使用\b匹配单词的边界eg.正则表达式可匹配字符串不可匹配字符串\blet\bletletter,hamlet3.\A和\z在确保字符串所包含的是某个表达式,而不是其他内容时很用。eg.要判断Text控件是否包含单词"sophia",而不含任何额外的字符、换行符或者空白。\Asophia\z4.句点字符(.)具有特殊的含义,若要表示字母字符本身的含义,在前面加一个反斜杠:\.C#正则表达式语法三、匹配而选一的字符序列|——匹配二选一eg.正则表达式可匹配字符串col(o|ou)rcolor,colour注意:\b(bill|ted)和\bbill|ted是不同的。后者还可以匹配"malted"因为\b元字符只应用于"bill"。C#正则表达式语法四、用量词匹配*——匹配0次或多次+——匹配1次或多次?——匹配0次或1次{n}——恰好匹配n次{n,}——至少匹配n次{n,m}——至少匹配n次,但不多于m次eg.正则表达式可匹配字符串brothers?brother,brotherseg.正则表达式可匹配字符串\bp\d{3,5}\b以p开头,且后跟3~5个数字结尾注意:也可以把量词与()一起使用,以便把该量词应用到整个字母序列。eg.正则表达式可匹配字符串(The)?schoolisbeautiful.schoolisbeautiful,Theschoolisbeautiful.C#正则表达式语法五、识别正则表达式和贪婪有些量词是贪婪的(greedy).他们会尽可能多的匹配字符。如量词*匹配0个或多个字符。假设要匹配字符串中任何HTML标签。你可能会用如下正则表达式:<.*>现有字符串Aquantifiercanbegreedy结果<.*>把quantifiercanbegreedy都匹配上了。要解决该问题,需要与量词一起使用一个特殊的非贪婪字符“?”,因此表达式变化如下:<.*?>这样就可以正确匹配、、、。?能强制量词尽可能少地匹配字符,?还可以用在以下几个量词中:*?——非贪婪的量词*+?——非贪婪的量词+??——非贪婪的量词?{n}?——非贪婪的量词{n}{n,}?——非贪婪的量词{n,}{n,m}?——非贪婪的量词{n,m}六、捕获和反向引用捕获组(capturegroup)就像是正则表达式中的变量。捕获组可以捕获正则表达式中的字符模式,并且由正则表达式后面的编号或名称来引用改模式。()——用来捕获其中的字符串\数字——用编号来引用eg.正则表达式可匹配字符串(\w)(\w)\2\1abba注意:1.反向引用用来匹配html标签非常有效如<(\w+)>\1>可以匹配等类似格式的标签。2.默认情况下,只要使用圆括号,就会捕获圆括号内所包含的字符,可以使用n选项来禁用这个默认行为(在第7条里会详细介绍),或者添加?:到圆括号中。eg.(?:sophia)或(?n:sophia)此时不会捕获sophia。(?<捕获组名称>)\k<捕获组名称>——用名称来引用eg.正则表达式可匹配字符串(?\w)abc\kxabcx注意:在替换模式中使用捕获组的格式略有不同,要用$1、$2等来按数值引用捕获,用${sophia}等名称来按名称引用捕获组七、设置正则表达式的选项eg.stringstr="sophia"
Groupg=m.Group(gnums[i]);
//获得这次匹配的组
Console.WriteLine("Group"+gnums[i]+"=["+g.ToString()+"]");
//计算这个组的起始位置和长度
CaptureCollectioncc=g.Captures;
for(intj=0;j{Capturec=cc[j];Console.WriteLine("Capture"+j+"=["+c.ToString()+"]Index="+c.Index+"Length="+c.Length);}}//下一个匹配m=m.NextMatch();}这个例子的输出如下所示:Group1=[abra]Capture0=[abracad]Index=0Length=7Capture1=[abra]Index=7Length=4Group2=[cad]Capture0=[cad]Index=4Length=3Group1=[abra]Capture0=[abracad]Index=12Length=7Capture1=[abra]Index=19Length=4Group2=[cad]Capture0=[cad]Index=16Length=3Group1=[abra]Capture0=[abracad]Index=24Length=7Capture1=[abra]Index=31Length=4Group2=[cad]Capture0=[cad]Index=28Length=3 我们首先从考查字符串pat开始,pat中包含有表达式。第一个capture是从第一个圆括号开始的,然后表达式将匹配到一个abra。第二个capture组从第二个圆括号开始,但第一个capture组还没有结束,这意味着第一个组匹配的结果是abracad,而第二个组的匹配结果仅仅是cad。因此如果通过使用?符号而使cad成为一项可选的匹配,匹配的结果就可能是abra或abracad。然后,第一个组就会结束,通过指定+符号要求表达式进行多次匹配。现在我们来看看匹配过程中发生的情况。首先,通过调用Regex的constructor方法建立表达式的一个实例,并在其中指定各种选项。在这个例子中,由于在表达式中有注释,因此选用了x选项,另外还使用了一些空格。打开x选项,表达式将会忽略注释和其中没有转义的空格。然后,取得表达式中定义的组的编号的清单。你当然可以显性地使用这些编号,在这里使用的是编程的方法。如果使用了命名的组,作为一种建立快速索引的途径这种方法也十分有效。接下来是完成第一次匹配。通过一个循环测试当前的匹配是否成功,接下来是从group1开始重复对组清单执行这一操作。在这个例子中没有使用group0的原因是group0是一个完全匹配的字符串,如果要通过收集全部匹配的字符串作为一个单一的字符串,就会用到group0了。我们跟踪每个group中的CaptureCollection。通常情况下每次匹配、每个group中只能有一个capture,但本例中的Group1则有两个capture:Capture0和Capture1。如果你仅需要Group1的ToString,就会只得到abra,当然它也会与abracad匹配。组中ToString的值就是其CaptureCollection中最后一个Capture的值,这正是我们所需要的。如果你希望整个过程在匹配abra后结束,就应该从表达式中删除+符号,让regex引擎知道我们只需要对表达式进行匹配。基于过程和基于表达式方法的比较 一般情况下,使用规则表达式的用户可以分为以下二大类:第一类用户尽量不使用规则表达式,而是使用过程来执行一些需要重复的操作;第二类用户则充分利用规则表达式处理引擎的功能和威力,而尽可能少地使用过程。对于我们大多数用户而言,最好的方案莫过于二者兼而用之了。我希望这篇文章能够说明.NET语言中regexp类的作用以及它在性能和复杂性之间的优、劣点。基于过程的模式 我们在编程中经常需要用到的一个功能是对字符串中的一部分进行匹配或其他一些对字符串处理,下面是一个对字符串中的单词进行匹配的例子:stringtext="thequickredfoxjumpedoverthelazybrowndog.";System.Console.WriteLine("text=["+text+"]");stringresult="";stringpattern=@"\w+|\W+";foreach(MatchminRegex.Matches(text,pattern)){//取得匹配的字符串stringx=m.ToString();//如果第一个字符是小写if(char.IsLower(x[0]))//变成大写x=char.ToUpper(x[0])+x.Substring(1,x.Length-1);//收集所有的字符result+=x;}System.Console.WriteLine("result=["+result+"]");正象上面的例子所示,我们使用了C#语言中的foreach语句处理每个匹配的字符,并完成相应的处理,在这个例子中,新创建了一个result字符串。这个例子的输出所下所示:text=[thequickredfoxjumpedoverthelazybrowndog.]result=[TheQuickRedFoxJumpedOverTheLazyBrownDog.]基于表达式的模式 完成上例中的功能的另一条途径是通过一个MatchEvaluator,新的代码如下所示:staticstringCapText(Matchm){//取得匹配的字符串stringx=m.ToString();//如果第一个字符是小写if(char.IsLower(x[0]))//转换为大写returnchar.ToUpper(x[0])+x.Substring(1,x.Length-1);returnx;}staticvoidMain(){stringtext="thequickredfoxjumpedoverthelazybrowndog.";System.Console.WriteLine("text=["+text+"]");stringpattern=@"\w+";stringresult=Regex.Replace(text,pattern,newMatchEvaluator(Test.CapText));System.Console.WriteLine("result=["+result+"]");}同时需要注意的是,由于仅仅需要对单词进行修改而无需对非单词进行修改,这个模式显得非常简单。介绍一下C#正则表达式语法的相关规则,包括字符的规则、字母文本的规则等等。希望本文能对大家了解C#正则表达式语法有所帮助。正则表达式通常包含字母文本(Literaltext)和元字符(metacharacter)字母文本指的是普通文本如"abcde"可匹配字符串中任何包含"abcde"的字符串。元字符则更加灵活运用通用的表达式匹配所有符合此表达式规律的字符串。C#正则表达式语法一、匹配单个字符[]——从中选择一个字符匹配中间支持的类型:单词字符([ae])、非单词字符([!?;@#$*])、字母范围([A-Z])、数字范围([0])eg.正则表达式可匹配字符串[ae]ffectaffect,effect(此例中"[ae]"为元字符,"ffect"为字母文本)注意:1.要在字符类中匹配连字符,那么把连字符号作为第一个字符列出即可。2.可以在单个正则表达式中包含多个字符类。eg.[01][0-9]:[0-5][0-9][ap]m可以用来匹配如12:59pm格式的所有时间^——排除某些字符(在[]中表此意,还可表示字符串的开头)eg.正则表达式可匹配字符串不可匹配字符串m[^a]tmet,mit,m&t……matC#正则表达式语法二、匹配特殊字符可以使用的特殊字符:\t——匹配制表符\r——匹配硬回车符\f——匹配换页符\n——匹配换行符描述表示字符类的元字符:.——匹配任何除了\n以外的字符(或者在单行模式中的任何字符)\w——匹配任何单词字符(任何字母或数字)\W——匹配任何非单词字符(除了字母和数字以外的任何字符)\s——匹配任何空白字符(包括空格、换行、制表符等)\S——匹配任何非空白字符(除了空格、换行、制表符等的任何字符)\d——匹配任何数字字符(0~9的数字)\D——匹配任何非数字字符(除了0~9以外的任何字符)表示字符串中字符位置:^——匹配字符串的开头(或者多行模式下行的开头)。$——匹配字符串的结尾,或者是字符串结尾“\n”之前的最后一个字符,或者是多行模式中的行结尾。\A——匹配字符串的开头(忽略多行模式)\Z——匹配字符串的结尾或字符串结尾“\n”之前的最后一个字符(忽略多行模式)。\z——匹配字符串的结尾。\G——匹配当前搜索开始的位置。\b——匹配单词的边界。\B——匹配单词的非边界。注意:1.句点字符(.)特别有用。可以用它来表示任何一个字符。eg.正则表达式可匹配字符串01.17.8401/17/84,01-17-84,011784,01.17.842.可以使用\b匹配单词的边界eg.正则表达式可匹配字符串不可匹配字符串\blet\bletletter,hamlet3.\A和\z在确保字符串所包含的是某个表达式,而不是其他内容时很用。eg.要判断Text控件是否包含单词"sophia",而不含任何额外的字符、换行符或者空白。\Asophia\z4.句点字符(.)具有特殊的含义,若要表示字母字符本身的含义,在前面加一个反斜杠:\.C#正则表达式语法三、匹配而选一的字符序列|——匹配二选一eg.正则表达式可匹配字符串col(o|ou)rcolor,colour注意:\b(bill|ted)和\bbill|ted是不同的。后者还可以匹配"malted"因为\b元字符只应用于"bill"。C#正则表达式语法四、用量词匹配*——匹配0次或多次+——匹配1次或多次?——匹配0次或1次{n}——恰好匹配n次{n,}——至少匹配n次{n,m}——至少匹配n次,但不多于m次eg.正则表达式可匹配字符串brothers?brother,brotherseg.正则表达式可匹配字符串\bp\d{3,5}\b以p开头,且后跟3~5个数字结尾注意:也可以把量词与()一起使用,以便把该量词应用到整个字母序列。eg.正则表达式可匹配字符串(The)?schoolisbeautiful.schoolisbeautiful,Theschoolisbeautiful.C#正则表达式语法五、识别正则表达式和贪婪有些量词是贪婪的(greedy).他们会尽可能多的匹配字符。如量词*匹配0个或多个字符。假设要匹配字符串中任何HTML标签。你可能会用如下正则表达式:<.*>现有字符串Aquantifiercanbegreedy结果<.*>把quantifiercanbegreedy都匹配上了。要解决该问题,需要与量词一起使用一个特殊的非贪婪字符“?”,因此表达式变化如下:<.*?>这样就可以正确匹配、、、。?能强制量词尽可能少地匹配字符,?还可以用在以下几个量词中:*?——非贪婪的量词*+?——非贪婪的量词+??——非贪婪的量词?{n}?——非贪婪的量词{n}{n,}?——非贪婪的量词{n,}{n,m}?——非贪婪的量词{n,m}六、捕获和反向引用捕获组(capturegroup)就像是正则表达式中的变量。捕获组可以捕获正则表达式中的字符模式,并且由正则表达式后面的编号或名称来引用改模式。()——用来捕获其中的字符串\数字——用编号来引用eg.正则表达式可匹配字符串(\w)(\w)\2\1abba注意:1.反向引用用来匹配html标签非常有效如<(\w+)>\1>可以匹配等类似格式的标签。
Capturec=cc[j];
Console.WriteLine("Capture"+j+"=["+c.ToString()
+"]Index="+c.Index+"Length="+c.Length);
}
//下一个匹配
m=m.NextMatch();
这个例子的输出如下所示:
Group1=[abra]
Capture0=[abracad]Index=0Length=7
Capture1=[abra]Index=7Length=4
Group2=[cad]
Capture0=[cad]Index=4Length=3
Capture0=[abracad]Index=12Length=7
Capture1=[abra]Index=19Length=4
Capture0=[cad]Index=16Length=3
Capture0=[abracad]Index=24Length=7
Capture1=[abra]Index=31Length=4
Capture0=[cad]Index=28Length=3
我们首先从考查字符串pat开始,pat中包含有表达式。
第一个capture是从第一个圆括号开始的,然后表达式将匹配到一个abra。
第二个capture组从第二个圆括号开始,但第一个capture组还没有结束,这意味着第一个组匹配的结果是abracad,而第二个组的匹配结果仅仅是cad。
因此如果通过使用?
符号而使cad成为一项可选的匹配,匹配的结果就可能是abra或abracad。
然后,第一个组就会结束,通过指定+符号要求表达式进行多次匹配。
现在我们来看看匹配过程中发生的情况。
首先,通过调用Regex的constructor方法建立表达式的一个实例,并在其中指定各种选项。
在这个例子中,由于在表达式中有注释,因此选用了x选项,另外还使用了一些空格。
打开x选项,表达式将会忽略注释和其中没有转义的空格。
然后,取得表达式中定义的组的编号的清单。
你当然可以显性地使用这些编号,在这里使用的是编程的方法。
如果使用了命名的组,作为一种建立快速索引的途径这种方法也十分有效。
接下来是完成第一次匹配。
通过一个循环测试当前的匹配是否成功,接下来是从group1开始重复对组清单执行这一操作。
在这个例子中没有使用group0的原因是group0是一个完全匹配的字符串,如果要通过收集全部匹配的字符串作为一个单一的字符串,就会用到group0了。
我们跟踪每个group中的CaptureCollection。
通常情况下每次匹配、每个group中只能有一个capture,但本例中的Group1则有两个capture:
Capture0和Capture1。
如果你仅需要Group1的ToString,就会只得到abra,当然它也会与abracad匹配。
组中ToString的值就是其CaptureCollection中最后一个Capture的值,这正是我们所需要的。
如果你希望整个过程在匹配abra后结束,就应该从表达式中删除+符号,让regex引擎知道我们只需要对表达式进行匹配。
基于过程和基于表达式方法的比较
一般情况下,使用规则表达式的用户可以分为以下二大类:
第一类用户尽量不使用规则表达式,而是使用过程来执行一些需要重复的操作;第二类用户则充分利用规则表达式处理引擎的功能和威力,而尽可能少地使用过程。
对于我们大多数用户而言,最好的方案莫过于二者兼而用之了。
我希望这篇文章能够说明.NET语言中regexp类的作用以及它在性能和复杂性之间的优、劣点。
基于过程的模式
我们在编程中经常需要用到的一个功能是对字符串中的一部分进行匹配或其他一些对字符串处理,下面是一个对字符串中的单词进行匹配的例子:
stringtext="thequickredfoxjumpedoverthelazybrowndog.";
System.Console.WriteLine("text=["+text+"]");
stringresult="";
stringpattern=@"\w+|\W+";
foreach(MatchminRegex.Matches(text,pattern))
//取得匹配的字符串
stringx=m.ToString();
//如果第一个字符是小写
if(char.IsLower(x[0]))
//变成大写
x=char.ToUpper(x[0])+x.Substring(1,x.Length-1);
//收集所有的字符
result+=x;
System.Console.WriteLine("result=["+result+"]");
正象上面的例子所示,我们使用了C#语言中的foreach语句处理每个匹配的字符,并完成相应的处理,在这个例子中,新创建了一个result字符串。
这个例子的输出所下所示:
text=[thequickredfoxjumpedoverthelazybrowndog.]
result=[TheQuickRedFoxJumpedOverTheLazyBrownDog.]
基于表达式的模式
完成上例中的功能的另一条途径是通过一个MatchEvaluator,新的代码如下所示:
staticstringCapText(Matchm)
//转换为大写
returnchar.ToUpper(x[0])+x.Substring(1,x.Length-1);
returnx;
staticvoidMain()
stringtext="thequickredfoxjumpedoverthe
lazybrowndog.";
stringpattern=@"\w+";
stringresult=Regex.Replace(text,pattern,
newMatchEvaluator(Test.CapText));
同时需要注意的是,由于仅仅需要对单词进行修改而无需对非单词进行修改,这个模式显得非常简单。
介绍一下C#正则表达式语法的相关规则,包括字符的规则、字母文本的规则等等。
希望本文能对大家了解C#正则表达式语法有所帮助。
正则表达式通常包含字母文本(Literaltext)和元字符(metacharacter)
字母文本指的是普通文本如"abcde"可匹配字符串中任何包含"abcde"的字符串。
元字符则更加灵活运用通用的表达式匹配所有符合此表达式规律的字符串。
C#正则表达式语法一、匹配单个字符
[]——从中选择一个字符匹配
中间支持的类型:
单词字符([ae])、非单词字符([!
?
;@#$*])、字母范围([A-Z])、数字范围([0])
eg.正则表达式可匹配字符串
[ae]ffectaffect,effect
(此例中"[ae]"为元字符,"ffect"为字母文本)
注意:
1.要在字符类中匹配连字符,那么把连字符号作为第一个字符列出即可。
2.可以在单个正则表达式中包含多个字符类。
eg.[01][0-9]:
[0-5][0-9][ap]m可以用来匹配如12:
59pm格式的所有时间
^——排除某些字符(在[]中表此意,还可表示字符串的开头)
eg.正则表达式可匹配字符串不可匹配字符串
m[^a]tmet,mit,m&t……mat
C#正则表达式语法二、匹配特殊字符
可以使用的特殊字符:
\t——匹配制表符
\r——匹配硬回车符
\f——匹配换页符
\n——匹配换行符
描述表示字符类的元字符:
.——匹配任何除了\n以外的字符(或者在单行模式中的任何字符)
\w——匹配任何单词字符(任何字母或数字)
\W——匹配任何非单词字符(除了字母和数字以外的任何字符)
\s——匹配任何空白字符(包括空格、换行、制表符等)
\S——匹配任何非空白字符(除了空格、换行、制表符等的任何字符)
\d——匹配任何数字字符(0~9的数字)
\D——匹配任何非数字字符(除了0~9以外的任何字符)
表示字符串中字符位置:
^——匹配字符串的开头(或者多行模式下行的开头)。
$——匹配字符串的结尾,或者是字符串结尾“\n”之前的最后一个字符,或者是多行模式中的行结尾。
\A——匹配字符串的开头(忽略多行模式)
\Z——匹配字符串的结尾或字符串结尾“\n”之前的最后一个字符(忽略多行模式)。
\z——匹配字符串的结尾。
\G——匹配当前搜索开始的位置。
\b——匹配单词的边界。
\B——匹配单词的非边界。
1.句点字符(.)特别有用。
可以用它来表示任何一个字符。
01.17.8401/17/84,01-17-84,011784,01.17.84
2.可以使用\b匹配单词的边界
\blet\bletletter,hamlet
3.\A和\z在确保字符串所包含的是某个表达式,而不是其他内容时很用。
eg.要判断Text控件是否包含单词"sophia",而不含任何额外的字符、换行符或者空白。
\Asophia\z
4.句点字符(.)具有特殊的含义,若要表示字母字符本身的含义,在前面加一个反斜杠:
\.
C#正则表达式语法三、匹配而选一的字符序列
|——匹配二选一
col(o|ou)rcolor,colour
\b(bill|ted)和\bbill|ted是不同的。
后者还可以匹配"malted"因为\b元字符只应用于"bill"。
C#正则表达式语法四、用量词匹配
*——匹配0次或多次
+——匹配1次或多次
——匹配0次或1次
{n}——恰好匹配n次
{n,}——至少匹配n次
{n,m}——至少匹配n次,但不多于m次
brothers?
brother,brothers
\bp\d{3,5}\b以p开头,且后跟3~5个数字结尾
也可以把量词与()一起使用,以便把该量词应用到整个字母序列。
(The)?
schoolisbeautiful.schoolisbeautiful,Theschoolisbeautiful.
C#正则表达式语法五、识别正则表达式和贪婪
有些量词是贪婪的(greedy).他们会尽可能多的匹配字符。
如量词*匹配0个或多个字符。
假设要匹配字符串中任何HTML标签。
你可能会用如下正则表达式:
<.*>
现有字符串Aquantifiercanbegreedy
结果<.*>把quantifiercanbegreedy都匹配上了。
要解决该问题,需要与量词一起使用一个特殊的非贪婪字符“?
”,因此表达式变化如下:
<.*?
>
这样就可以正确匹配、、、。
能强制量词尽可能少地匹配字符,?
还可以用在以下几个量词中:
*?
——非贪婪的量词*
+?
——非贪婪的量词+
——非贪婪的量词?
{n}?
——非贪婪的量词{n}
{n,}?
——非贪婪的量词{n,}
{n,m}?
——非贪婪的量词{n,m}
六、捕获和反向引用
捕获组(capturegroup)就像是正则表达式中的变量。
捕获组可以捕获正则表达式中的字符模式,并且由正则表达式后面的编号或名称来引用改模式。
()——用来捕获其中的字符串
\数字——用编号来引用
eg.
正则表达式可匹配字符串
(\w)(\w)\2\1abba
1.反向引用用来匹配html标签非常有效如<(\w+)>\1>可以匹配
2.默认情况下,只要使用圆括号,就会捕获圆括号内所包含的字符,可以使用n选项来禁用这个默认行为(在第7条里会详细介绍),或者添加?
:
到圆括号中。
eg.(?
:
sophia)或(?
n:
sophia)此时不会捕获sophia。
(?
<捕获组名称>)\k<捕获组名称>——用名称来引用
(?
\w)abc\kxabcx
在替换模式中使用捕获组的格式略有不同,要用$1、$2等来按数值引用捕获,用${sophia}等名称来按名称引用捕获组
七、设置正则表达式的选项
stringstr="
RegExobjRegEx=newRegEx("(.*?
)");
Response.Write(objRegEx.Replace(str,"$2"));
i——所执行的匹配是不区分大小写的(.net中的属性为IgnoreCase)
m——指定多行模式(.net中的属性为Multiline)
n——只捕获显示命名或编号的组(.net中的属性为ExplicitCapture)
c——编译正则表达式,这样会产生较快的执行速度,但启动会变慢(.net中的属性为Compiled)
s——指定单行模式(.net中的属性为SingleLine)
x——消除非转义空白字符和注释(.net中的属性为IgnorePatternWhitespace)
r——搜索从右到左进行(.net中的属性为RightToLeft)
-——表示禁用。
im-r:
sophia)允许不区分大小写匹配sophia,使用多行模式,但禁用了从右到左的匹配。
1.m会影响如何解析起始元字符(^)和结束元字符($)。
在默认情况^和$只匹配整个字符串的开头,即使字符串包含多行文本。
如果启用了m,那么它们就可以匹配每行文本的开头和结尾。
2.s会影响如何解析句点元字符(.)。
通常一个句点能匹配除了换行符以外的所有字符。
但在单行模式下,句点也能匹配一个换行符。
SOMEEXAMPLE
只能输入数字:
"^[0-9]*$"。
只能输入n位的数字:
"^\d{n}$"。
只能输入至少n位的数字:
"^\d{n,}$"。
只能输入m~n位的数字:
。
"^\d{m,n}$"
只能输入零和非零开头的数字:
"^(0|[1-9][0-9]*)$"。
只能输入有两位小数的正实数:
"^[0-9]+(.[0-9]{2})?
$"。
只能输入有1~3位小数的正实数:
"^[0-9]+(.[0-9]{1,3})?
只能输入非零的正整数:
"^\+?
[1-9][0-9]*$"。
只能输入非零的负整数:
"^\-[1-9][]0-9"*$。
只能输入长度为3的字符:
"^.{3}$"。
只能输入由26个英文字母组成的字符串:
"^[A-Za-z]+$"。
只能输入由26个大写英文字母组成的字符串:
"^[A-Z]+$"。
只能输入由26个小写英文字母组成的字符串:
"^[a-z]+$"。
只能输入由数字和26个英文字母组成的字符串:
"^[A-Za-z0-9]+$"。
只能输入由数字、26个英文字母或者下划线组成的字符串:
"^\w+$"。
验证用户密码:
"^[a-zA-Z]\w{5,17}$"正确格式为:
以字母开头,长度在6~18之间,只能包含字符、数字和下划线。
验证是否含有^%&',;=?
$\"等字符:
"[^%&',;=?
$\x22]+"。
只能输入汉字:
"^[\u4e00-\u9fa5]{0,}$"
验证Email地址:
"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"。
验证InternetURL:
"^http:
//([\w-]+\.)+[\w-]+(/[\w-./?
%&=]*)?
验证电话号码:
"^(\(\d{3,4}-)|\d{3.4}-)?
\d{7,8}$"正确格式为:
"XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX"。
验证身份证号(15位或18位数字):
"^\d{15}|\d{18}$"。
验证一年的12个月:
"^(0?
[1-9]|1[0-2])$"正确格式为:
"01"~"09"和"1"~"12"。
验证一个月的31天:
"^((0?
[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01"~"09"和"1"~"31"。
利用正则表达式限制网页表单里的文本框输入内容:
用正则表达式限制只能输入中文:
用正则表达式限制只能输入全角字符:
用正则表达式限制只能输入数字:
用正则表达式限制只能输入数字和英文:
得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2