[.net 面向对象程序设计进阶] (2) 正则表达式 (一) 快速入门

[.net 面向对象程序设计进阶] (2) 正则表达式 (一) 快速入门

1. 什么是正则表达式?

1.1 正则表达式概念

正则表达式,又称正则表示法,英文名:Regular Expression(简写为regexregexpRE),是计算机科学的一个重要概念。他是用一种数学算法来解决计算机程序中的文本检索、区配等问题。

1.2 正则表达式语言支持 

     正则表达式其实与语言无关,在很多语言中都提供了支持 ,包括最常用的脚本语言Javascript。当然C#语言也毫不例外的提供了很好的支持。
     正则表达式语法支持情况如下表:

命令或环境

.

[ ]

^

$

\( \)

\{ \}

?

+

|

( )

vi

 

 

 

 

 

Visual C++

 

 

 

 

 

awk

 

 

sed

 

 

 

 

delphi

 

python

 

 

 

 

java

 

 

 

 

javascript

 

php

 

 

 

 

 

perl

 

C#

 

 

1.3 正式表达式的应用 

在进阶系列文章的开始就介绍正则表达式,是因为他非常常用,在我们开发应用程序的时候,需要对输入内容进行格式校验,需要对复杂的字符中找出规律检索出我们想要的部分。对于刚接触的人来说,比较晦涩难懂,当你读完本篇以后,就会感觉正则表达式并不是什么复杂的东西。

因此使用正则表达式,可以帮助我们解决以下问题:

A.检索: 可以通过正则表达式,从字符串中获取我们想要的特定部分。

B.匹配:给定的字符串是否符合正则表达式的过滤逻辑 

下面几种应用场景,都特别适合正则表达式来解决

A.在论坛或博客中发贴时过滤敏感的字词

B.在应用软件中进行输入格式校验时

C.对一段复杂文本中进行有规则的替换时

D.将一段复杂文本按一定的规则变为另一种形式时 

下面我们会介绍正则表达式的基础知识。

2. 正则表达式的组成

一个正则表达式就是由普通字符以及特殊字符(称为元字符)组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

下面,我把特殊字符,也就是元字符列举一下

元字符

描述

\

将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“\\n”匹配\n“\n”匹配换行符。序列“\\”匹配“\”“\(”则匹配“(”。即相当于多种编程语言中都有的转义字符的概念。

^

匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”“\r”之后的位置。

$

匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“\n”“\r”之前的位置。

*

匹配前面的子表达式任意次。例如,zo*能匹配“z”“zo”以及“zoo”*等价于{0,}

+

匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”+等价于{1,}

?

匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”“does”中的“do”?等价于{0,1}

{n}

n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o

{n,}

n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o“o{1,}”等价于“o+”“o{0,}”则等价于“o*”

{n,m}

mn均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。

?

当该字符紧跟在任何一个其他限制符(*,+,?{n}{n,}{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”“o+?”将匹配单个“o”,而“o+”将匹配所有“o”

.

匹配除“\r\n”之外的任何单个字符。要匹配包括“\r\n”在内的任何字符,请使用像“[\s\S]”的模式。

(pattern)

匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“\(”“\)”

(?:pattern)

匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。

(?=pattern)

正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

(?!pattern)

正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”

(?<=pattern)

反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”

(?<!pattern)

反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”

x|y

匹配xy。例如,“z|food”能匹配“z”“food”"zood"(此处请谨慎)“(z|f)ood”则匹配“zood”“food”

[xyz]

字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”

[^xyz]

负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”

[a-z]

字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”“z”范围内的任意小写字母字符。

注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围如果出字符组的开头,则只能表示连字符本身.

[^a-z]

负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”“z”范围内的任意字符。

\b

匹配一个单词边界,也就是指单词和空格间的位置(即正则表达式的匹配有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”

\B

匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”

\cx

匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Za-z之一。否则,将c视为一个原义的“c”字符。

\d

匹配一个数字字符。等价于[0-9]

\D

匹配一个非数字字符。等价于[^0-9]

\f

匹配一个换页符。等价于\x0c\cL

\n

匹配一个换行符。等价于\x0a\cJ

\r

匹配一个回车符。等价于\x0d\cM

\s

匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]

\S

匹配任何可见字符。等价于[^ \f\n\r\t\v]

\t

匹配一个制表符。等价于\x09\cI

\v

匹配一个垂直制表符。等价于\x0b\cK

\w

匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。

\W

匹配任何非单词字符。等价于“[^A-Za-z0-9_]”

\xn

匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。

\num

匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。

\n

标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。

\nm

标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若nm均为八进制数字(0-7),则\nm将匹配八进制转义值nm

\nml

如果n为八进制数字(0-7),且ml均为八进制数字(0-7),则匹配八进制转义值nml

\un

匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(©)。

\< \>

匹配词(word)的开始(\<)和结束(\>)。例如正则表达式\<the\>能够匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:这个元字符不是所有的软件都支持的。

\( \)

将 \( 和 \) 之间的表达式定义为group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 \9 的符号来引用。

|

将两个匹配条件进行逻辑Or)运算。例如正则表达式(him|her) 匹配"it belongs to him""it belongs to her",但是不能匹配"it belongs to them."。注意:这个元字符不是所有的软件都支持的。

+

匹配1或多个正好在它之前的那个字符。例如正则表达式9+匹配999999等。注意:这个元字符不是所有的软件都支持的。

?

匹配01个正好在它之前的那个字符。注意:这个元字符不是所有的软件都支持的。

{i} {i,j}

匹配指定数目的字符,这些字符是在它之前的表达式定义的。例如正则表达式A[0-9]{3} 能够匹配字符"A"后面跟着正好3个数字字符的串,例如A123A348等,但是不匹配A1234。而正则表达式[0-9]{4,6} 匹配连续的任意4个、5个或者6个数字

 小伙伴们不要被上面的表格吓坏了,下面我会以C#中应用正则表达式为例一一说明的,上面的表格中的元字符在今后的应用中,可以作为查阅和参考。

3. C#中使用正则表达式

3.1 C#中正则表达式的命名空间

System.Text.RegularExpressions 命名空间包含一些类,这些类提供对 .NET Framework 正则表达式引擎的访问。 该命名空间提供正则表达式功能,可以从运行在 Microsoft .NET Framework 内的任何平台或语言中使用该功能。 除了此命名空间中包含的类型外,System.Configuration.RegexStringValidator 类还允许您确定特定字符串是否与某个正则表达式模式相符。

总结一下,在.net中有两个命名空间用于操作正则表达式

A.System.Text.RegularExpressions 命名空间下在的类、委托、枚举https://msdn.microsoft.com/zh-cn/library/system.text.regularexpressions.aspx

B.System.Configuration.RegexStringValidator 类

3.2 常用的操作正则表达式的方法和委托

其中System.Text.RegularExpressions 下的Regex类中提供了很多静态方法(比较常用的有IsMatch、Match、Matches、Replace、Split等)和委托MatchEvaluator .

3.2.1 静态方法IsMatch

IsMatch 方法返回值为一个布尔型,主要用于判断指定的字符串是否与正则表达式字符串匹配,它有三个重载方法

bool IsMatch(string input, string pattern);

参数: input:       要搜索匹配项的字符串。

      pattern:     要匹配的正则表达式模式。
 返回结果:  如果正则表达式找到匹配项,则为 true;否则,为 false。

bool IsMatch(string input, string pattern, RegexOptions options);

参数: input:       要搜索匹配项的字符串。

      pattern:     要匹配的正则表达式模式。
      options:     枚举值的一个按位组合,这些枚举值提供匹配选项。
返回结果:  如果正则表达式找到匹配项,则为 true;否则,为 false。

options下面有详细说明

bool IsMatch(string input, string pattern, RegexOptions options, TimeSpan matchTimeout);

参数: input:        要搜索匹配项的字符串。

      pattern:      要匹配的正则表达式模式。
      options:      枚举值的一个按位组合,这些枚举值提供匹配选项。
      matchTimeout: 超时间隔,或 System.Text.RegularExpressions.Regex.InfiniteMatchTimeout 指示该方法不应超时。
返回结果:  如果正则表达式找到匹配项,则为 true;否则,为 false。

3.2.2 关于参数RegexOptions options

正则表达式选项RegexOptions有如下一下选项,详细说明请参考联机帮助

RegexOptions枚举值

内联标志

简单说明

ExplicitCapture

n

只有定义了命名或编号的组才捕获

IgnoreCase

i

不区分大小写

IgnorePatternWhitespace

x

消除模式中的非转义空白并启用由 # 标记的注释。

MultiLine

m

多行模式,其原理是修改了^和$的含义

SingleLine

s

单行模式,和MultiLine相对应

这里我提到内联标志,是因为相对于用RegexOptions在new Regex时定义Regex表达式的全局选项来说,内联标志可以更小粒度(以组为单位)的定义匹配选项,从而更方便表达我们的思想

语法是这样的:(?i:expression)为定义一个选项,(?-i:expression)为删除一个选项,(?i-s:expression)则定义i,删除s,是的,我们可以一次定义很多个选项。这样,通过内联选项,你就可以在一个Regex中定义一个组为匹分大小写的,一个组不匹分大小写的

3.2.3  静态方法Match

静态方法Match,使用指定的匹配选项在输入字符串中搜索指定的正则表达式的第一个匹配项。 返回一个包含有关匹配的信息的对象。同样有三个重载方法,参数和IsMatch方法相同。此外,在Regex类中,还有一个同名的非静态方法,适用于多个实例的情况下,效率更高一些。

Match Match(string input, string pattern);
Match Match(string input, string pattern, RegexOptions options);
Match Match(string input, string pattern, RegexOptions options, TimeSpan matchTimeout);

3.2.4  静态方法Matches

静态方法Matches,在指定的输入字符串中搜索指定的正则表达式的所有匹配项。跟上面方法不同之处,就是这个方法返回的是所有匹配项,他同样有三个重载方法,并且参数和Match方法完全相同

Match Matches(string input, string pattern);
Match Matches(string input, string pattern, RegexOptions options);
Match Matches(string input, string pattern, RegexOptions options, TimeSpan matchTimeout);

3.2.5  Replace函数有四个重载函数

我们知道正则表达式主要是实现验证,提取,分割,替换字符的功能.Replace函数是实现替换功能的.

1 )Replace(string input,string pattern,string replacement)  

//input是源字符串,pattern是匹配的条件,replacement是替换的内容,就是把符合匹配条件pattern的内容转换成它

比如string result = Regex.Replace("abc", "ab", "##");  

//结果是##c,就是把字符串abc中的ab替换成##

2 )Replace(string input,string pattern,string replacement,RegexOptions options)      

//RegexOptions是一个枚举类型,用来做一些设定.

//前面用注释时就用到了RegexOptions.IgnorePatternWhitespace.如果在匹配时忽略大小写就可以用RegexOptions.IgnoreCase

比如string result = Regex.Replace("ABc", "ab", "##",RegexOptions.IgnoreCase);

如果是简单的替换用上面两个函数就可以实现了.但如果有些复杂的替换,比如匹配到很多内容,不同的内容要替换成不同的字符.就需要用到下面两个函数

3 )Replace(string input,string pattern,MatchEvaluator evaluator);    

//evaluator是一个代理,其实简单的说是一个函数指针,把一个函数做为参数参进来

//由于C#里没有指针就用代理来实现类似的功能.你可以用代理绑定的函数来指定你要实现的复杂替换.

4 )Replace(string input,string pattern,MatchEvaluator evaluator,RegexOptions options);

//这个函数上上面的功能一样,只不过多了一点枚举类型来指定是否忽略大小写等设置

3.2.6 静态方法Split拆分文本

使用正则表达式匹配的位置,将文本拆分为一个字符串数组,同样有三个重载方法,返回值为字符串数组

string[] Split(string input, string pattern);
string[] Match(string input, string pattern, RegexOptions options);
string[] Match(string input, string pattern, RegexOptions options, TimeSpan matchTimeout);

下面我们会分别介绍最常用的正则表达式的使用

4. @符号

在“@”虽然并非C#正则表达式的“成员”,但是它经常与C#正则表达式出双入对。“@”表示,跟在它后面的字符串是个“逐字字符串”,

示例:

string strFirst="C:\\Program Files\\IIS";
string strSecond=@"C:\Program Files\IIS";
Console.WriteLine(strFirst);
Console.WriteLine(strSecond);

以上定义字符串是等价的。

5. 定位字符

字符

说明

\b

匹配单词的开始或结束

\B

匹配非单词的开始或结束

^

匹配必须出现在字符串的开头或行的开头

$

匹配必须出现在以下位置:字符串结尾、字符串结尾处的 \n 之前或行的结尾。

\A

指定匹配必须出现在字符串的开头(忽略 Multiline 选项)。

\z

指定匹配必须出现在字符串的结尾(忽略 Multiline 选项)。

\z

指定匹配必须出现在字符串的结尾或字符串结尾处的 \n 之前(忽略 Multiline 选项)。

\G

指定匹配必须出现在上一个匹配结束的地方。与 Match.NextMatch() 一起使用时,此断言确保所有匹配都是连续的。

表 定位元字符

示例一:区配开始 ^

string str = "I am Blue cat";           
Console.WriteLine(Regex.Replace(str, "^","准备开始:"));

输出结果为:

 

示例二: 区始结束 $

string str = "I am Blue cat";           
Console.WriteLine(Regex.Replace(str, "$", "  结束了!"));

输出结果为:

 

6. 字符转义 \

当我们要查询元字符时,比如查询 * 或 . 必须使用转义符 \,当然查询/必须使用\\

7. 基本语法元字符

字符

说明

.

匹配除换行符以外的任意字符

\w

匹配字母、数字、下线下、汉字

(指大小写字母、0-9的数字、下划线_)

\W

\w的补集

( 除“大小写字母、0-9的数字、下划线_”之外

\s

匹配任意空白符

(包括换行符/n、回车符/r、制表符/t、垂直制表符/v、换页符/f)

\S

\s的补集

(\s定义的字符之外)

\d

匹配数字

(0-9数字)

\D

表示\d的补集

(0-9数字之外)

7基本语法元字符

示例一:校验只允许输入数字

string strCheckNum1 = "23423423a3", strCheckNum2 = "324234";
Console.WriteLine("匹配字符串"+strCheckNum1+"是否为数字:"+Regex.IsMatch(strCheckNum1, @"^\d*$"));
Console.WriteLine("匹配字符串" + strCheckNum2 + "是否为数字:" + Regex.IsMatch(strCheckNum2, @"^\d*$"));

输出结果为:

 

其中*表示重复多次检查字符,后面重复字符中会具体说明

示例二:校验只允许输入除大小写字母、0-9的数字、下划线_以外的任何字

//示例二:校验只允许输入除大小写字母、0-9的数字、下划线_以外的任何字符
string strCheckStr1 = "abcds_a", strCheckStr2 = "**&&((((2", strCheckStr3 = "**&&((((";
string regexStr = @"^\W*$";
Console.WriteLine("匹配字符串" + strCheckStr1 + "是否为除大小写字母、0-9的数字、下划线_以外的任何字符:" + Regex.IsMatch(strCheckStr1, regexStr));
Console.WriteLine("匹配字符串" + strCheckStr2 + "是否为除大小写字母、0-9的数字、下划线_以外的任何字符:" + Regex.IsMatch(strCheckStr2, regexStr));
Console.WriteLine("匹配字符串" + strCheckStr3 + "是否为除大小写字母、0-9的数字、下划线_以外的任何字符:" + Regex.IsMatch(strCheckStr3, regexStr));

输出结果为:

 

8. 反义

字符

说明

\W

\w的补集

( 除“大小写字母、0-9的数字、下划线_”之外)

\S

\s的补集

(\s定义的字符之外)

\D

表示\d的补集

(0-9数字之外)

\B

匹配不是单词开头或结束的位置

[^x]

匹配除了x以外的任意字符

[^adwz]

匹配除了adwz这几个字符以外的任意字符

表8 反义字符

上面的示例中已经使用到到反义了,我们举一个匹配除某些字母外的任意字符

示例:查找除ahou这之外的所有字符

//示例:查找除ahou这之外的所有字符
string strFind1 = "I am a Cat!", strFind2 = "My Name's Blue cat!";             
Console.WriteLine("除ahou这之外的所有字符,原字符为:" + strFind1 + "替换后:" + Regex.Replace(strFind1, @"[^ahou]","*")); Console.WriteLine("除ahou这之外的所有字符,原字符为:" + strFind2 + "替换后:" + Regex.Replace(strFind2, @"[^ahou]", "*"));

执行结果为:

 

9. 重复描述字符

字符

说明

{n} 

匹配前面的字符n

{n,}

匹配前面的字符n次或多于n

{n,m}

匹配前面的字符nm

?

重复零次或一次

+

重复一次或更多次

*

重复零次或更多次

重复描述字符

前面已经学习了 表示重复检索多个字符,下面我们具体应用一个实例

示例:校验输入内容是否为合法QQ(备注:QQ号为5-12位数字)

//示例:校验输入内容是否为合法QQ号(备注:QQ号为5 - 12位数字)
string isQq1 = "1233", isQq2 = "a1233", isQq3 = "0123456789123", isQq4 = "556878544";
string regexQq = @"^\d{5,12}$";
Console.WriteLine(isQq1+"是否为合法QQ号(5-12位数字):" + Regex.IsMatch(isQq1, regexQq));
Console.WriteLine(isQq2 + "是否为合法QQ号(5-12位数字):" + Regex.IsMatch(isQq2, regexQq));
Console.WriteLine(isQq3 + "是否为合法QQ号(5-12位数字):" + Regex.IsMatch(isQq3, regexQq));
Console.WriteLine(isQq4 + "是否为合法QQ号(5-12位数字):" + Regex.IsMatch(isQq4, regexQq));

运行结果为:

 

10. 择一匹配

字符

说明

|

将两个匹配条件进行逻辑Or)运算。

 示例一:查找数字或字母

//示例:查找数字或字母
string findStr1 = "ad(d3)-df";
string regexFindStr = @"[a-z]|\d";
string newStrFind=String.Empty;
MatchCollection newStr =  Regex.Matches(findStr1, regexFindStr);
 newStr.Cast<Match>().Select(m => m.Value).ToList<string>().ForEach(i => newStrFind += i);
Console.WriteLine(findStr1 + "中的字母和数字组成的新字符串为:" + newStrFind);

输出结果为:

 

示例二:将人名输出("zhangsan;lisi,wangwu.zhaoliu")

//示例:使用Split方法拆分
string strSplit = "zhangsan;lisi,wangwu.zhaoliu";
string regexSplitstr = @"[;]|[,]|[.]";
Regex.Split(strSplit, regexSplitstr).ToList().ForEach(i => Console.WriteLine(i));

输出结果如下:

示例三:校验国内电话号码(支持三种写法校验 A. 010-87654321 B. (010)87654321 C.01087654321 D.010 87654321)

//示例:校验国内电话号码(支持三种写法校验 A. 010-87654321  B. (010)87654321  C.01087654321  D.010 87654321)
string TelNumber1 = "(010)87654321", TelNumber2 = "010-87654321", TelNumber3 = "01087654321",
        TelNumber4 = "09127654321", TelNumber5 = "010)87654321",TelNumber6="(010-87654321",
        TelNumber7="91287654321";
Regex  RegexTelNumber1 =new Regex(@"\(?0\d{2,3}[-)]?\d{7,8}");
Console.WriteLine( "电话号码 "+TelNumber1+" 是否合法:" + RegexTelNumber1.IsMatch(TelNumber1));
Console.WriteLine("电话号码 " + TelNumber2 + " 是否合法:" + RegexTelNumber1.IsMatch(TelNumber2));
Console.WriteLine("电话号码 " + TelNumber3 + " 是否合法:" + RegexTelNumber1.IsMatch(TelNumber3));
Console.WriteLine("电话号码 " + TelNumber4 + " 是否合法:" + RegexTelNumber1.IsMatch(TelNumber4));
Console.WriteLine("电话号码 " + TelNumber5 + " 是否合法:" + RegexTelNumber1.IsMatch(TelNumber5));
Console.WriteLine("电话号码 " + TelNumber6 + " 是否合法:" + RegexTelNumber1.IsMatch(TelNumber6));
Console.WriteLine("电话号码 " + TelNumber7 + " 是否合法:" + RegexTelNumber1.IsMatch(TelNumber7));

Console.WriteLine("\n");

//上面未使用择一写法,导致TelNumber4和TelNumber5被合法化
//注意第二个分枝加了^ $符,表示从头到尾检索,不加的开始符,容易产生(010-87654321合法化(网上30分钟正则教程中,就存在此错误)
//改进使用择一写法后如下:

Console.WriteLine("\n");

Regex RegexTelNumber3 = new Regex(@"\(0\d{2,3}\)[- ]?\d{7,8}|^0\d{2,3}[- ]?\d{7,8}$");
       
Console.WriteLine("电话号码 " + TelNumber1 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber1));
Console.WriteLine("电话号码 " + TelNumber2 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber2));
Console.WriteLine("电话号码 " + TelNumber3 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber3));
Console.WriteLine("电话号码 " + TelNumber4 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber4));
Console.WriteLine("电话号码 " + TelNumber5 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber5));
Console.WriteLine("电话号码 " + TelNumber6 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber6));
Console.WriteLine("电话号码 " + TelNumber7 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber7));

运行结果如下:

 11. 要点:

A.本篇主要说明了正则表达式的基本元字符及使用方法举例

B.说明了C#中使用正则表达式的几种方法 

这些只是最基础的正则表达式的内容,学习本节内容,我们还不能完成复杂的正则表达式,

在下一节中,我们会继续说明正则表达式更深层次的使用。

下面附本节所有示例代码: 

 1 //开始和结束符 ^  $
 2 string str = "I am Blue cat";           
 3 Console.WriteLine(Regex.Replace(str, "^","准备开始:"));
 4 string str2 = "I am Blue cat";
 5 Console.WriteLine(Regex.Replace(str2, "$", "  结束了!"));
 6 
 7 string str3 = "myWord.*";
 8 Console.WriteLine(Regex.Replace(str3, ".*", ".doc"));
 9 
10 //示例:校验只允许输入数字
11 
12 string strCheckNum1 = "23423423a3", strCheckNum2 = "324234";
13 Console.WriteLine("匹配字符串"+strCheckNum1+"是否为数字:"+Regex.IsMatch(strCheckNum1, @"^\d*$"));
14 Console.WriteLine("匹配字符串" + strCheckNum2 + "是否为数字:" + Regex.IsMatch(strCheckNum2, @"^\d*$"));
15 
16 //示例二:校验只允许输入除大小写字母、0-9的数字、下划线_以外的任何字符
17 string strCheckStr1 = "abcds_a", strCheckStr2 = "**&&((((2", strCheckStr3 = "**&&((((";
18 string regexStr = @"^\W*$";
19 Console.WriteLine("匹配字符串" + strCheckStr1 + "是否为除大小写字母、0-9的数字、下划线_以外的任何字符:" + Regex.IsMatch(strCheckStr1, regexStr));
20 Console.WriteLine("匹配字符串" + strCheckStr2 + "是否为除大小写字母、0-9的数字、下划线_以外的任何字符:" + Regex.IsMatch(strCheckStr2, regexStr));
21 Console.WriteLine("匹配字符串" + strCheckStr3 + "是否为除大小写字母、0-9的数字、下划线_以外的任何字符:" + Regex.IsMatch(strCheckStr3, regexStr));
23 
24 //示例:查找除ahou这之外的所有字符
25 string strFind1 = "I am a Cat!", strFind2 = "My Name's Blue cat!";            
26 Console.WriteLine("除ahou这之外的所有字符,原字符为:" + strFind1 + "替换后:" + Regex.Replace(strFind1, @"[^ahou]","*"));
27 Console.WriteLine("除ahou这之外的所有字符,原字符为:" + strFind2 + "替换后:" + Regex.Replace(strFind2, @"[^ahou]", "*"));
28 
29 //示例:校验输入内容是否为合法QQ号(备注:QQ号为5 - 12位数字)
30 string isQq1 = "1233", isQq2 = "a1233", isQq3 = "0123456789123", isQq4 = "556878544";
31 string regexQq = @"^\d{5,12}$";
32 Console.WriteLine(isQq1+"是否为合法QQ号(5-12位数字):" + Regex.IsMatch(isQq1, regexQq));
33 Console.WriteLine(isQq2 + "是否为合法QQ号(5-12位数字):" + Regex.IsMatch(isQq2, regexQq));
34 Console.WriteLine(isQq3 + "是否为合法QQ号(5-12位数字):" + Regex.IsMatch(isQq3, regexQq));
35 Console.WriteLine(isQq4 + "是否为合法QQ号(5-12位数字):" + Regex.IsMatch(isQq4, regexQq));
37 
38 //示例:查找数字或字母
39 string findStr1 = "ad(d3)-df";
40 string regexFindStr = @"[a-z]|\d";
41 string newStrFind=String.Empty;
42 MatchCollection newStr =  Regex.Matches(findStr1, regexFindStr);
43 newStr.Cast<Match>().Select(m => m.Value).ToList<string>().ForEach(i => newStrFind += i);
44 Console.WriteLine(findStr1 + "中的字母和数字组成的新字符串为:" + newStrFind);
45 
46 //示例:使用Split方法拆分
47 string strSplit = "zhangsan;lisi,wangwu.zhaoliu";
48 string regexSplitstr = @"[;]|[,]|[.]";
49 Regex.Split(strSplit, regexSplitstr).ToList().ForEach(i => Console.WriteLine(i));
52 
53 //示例:校验国内电话号码(支持三种写法校验 A. 010-87654321  B. (010)87654321  C.01087654321  D.010 87654321)
54 string TelNumber1 = "(010)87654321", TelNumber2 = "010-87654321", TelNumber3 = "01087654321",
55         TelNumber4 = "09127654321", TelNumber5 = "010)87654321",TelNumber6="(010-87654321",
56         TelNumber7="91287654321";
57 Regex  RegexTelNumber1 =new Regex(@"\(?0\d{2,3}[-)]?\d{7,8}");
58 Console.WriteLine( "电话号码 "+TelNumber1+" 是否合法:" + RegexTelNumber1.IsMatch(TelNumber1));
59 Console.WriteLine("电话号码 " + TelNumber2 + " 是否合法:" + RegexTelNumber1.IsMatch(TelNumber2));
60 Console.WriteLine("电话号码 " + TelNumber3 + " 是否合法:" + RegexTelNumber1.IsMatch(TelNumber3));
61 Console.WriteLine("电话号码 " + TelNumber4 + " 是否合法:" + RegexTelNumber1.IsMatch(TelNumber4));
62 Console.WriteLine("电话号码 " + TelNumber5 + " 是否合法:" + RegexTelNumber1.IsMatch(TelNumber5));
63 Console.WriteLine("电话号码 " + TelNumber6 + " 是否合法:" + RegexTelNumber1.IsMatch(TelNumber6));
64 Console.WriteLine("电话号码 " + TelNumber7 + " 是否合法:" + RegexTelNumber1.IsMatch(TelNumber7));
65 
66 Console.WriteLine("\n");
67 
68 //上面未使用择一写法,导致TelNumber4和TelNumber5被合法化
69 //注意第二个分枝加了^ $符,表示从头到尾检索,不加的开始符,容易产生(010-87654321合法化(网上30分钟正则教程中,就存在此错误)
70 //改进使用择一写法后如下:
71 
72 Console.WriteLine("\n");
73 
74 Regex RegexTelNumber3 = new Regex(@"\(0\d{2,3}\)[- ]?\d{7,8}|^0\d{2,3}[- ]?\d{7,8}$");
75        
76 Console.WriteLine("电话号码 " + TelNumber1 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber1));
77 Console.WriteLine("电话号码 " + TelNumber2 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber2));
78 Console.WriteLine("电话号码 " + TelNumber3 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber3));
79 Console.WriteLine("电话号码 " + TelNumber4 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber4));
80 Console.WriteLine("电话号码 " + TelNumber5 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber5));
81 Console.WriteLine("电话号码 " + TelNumber6 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber6));
82 Console.WriteLine("电话号码 " + TelNumber7 + " 是否合法:" + RegexTelNumber3.IsMatch(TelNumber7));

==============================================================================================  

 返回目录

 <如果对你有帮助,记得点一下推荐哦,如有

有不明白或错误之处,请多交流>  

<对本系列文章阅读有困难的朋友,请先看《.net 面向对象编程基础》>

<转载声明:技术需要共享精神,欢迎转载本博客中的文章,但请注明版权及URL>

.NET 技术交流群:467189533    .NET 程序设计

==============================================================================================   

posted @ 2015-06-29 02:21  yubinfeng  阅读(3345)  评论(6编辑  收藏  举报