CSDN博客

img rickjelly2004

正则表达式(二)

发表于2004/7/1 9:39:00  525人阅读

标题     正则表达式(二)    dragontt(原作)
关键字     正则表达式

    在前一篇文章中,介绍了一些初步的正则表达式的基本概念,相信很多人对正则表达式的基本知识有所了解,接下来,我们结合一些实际的编程示例来掩饰说明正则表达式的作用。

    首先,我们先看几个实际的例子:

1.    验证输入字符是否全部为英文字符

javascript:

var ex = "^//w+$";

var re = new RegExp(ex,"i");

return re.test(str);

         VBScript

Dim regEx,flag,ex

ex = "^/w+$"

Set regEx = New RegExp

regEx.IgnoreCase = True

regEx.Global = True

regEx.Pattern = ex

flag = regEx.Test( str )

              C#

System.String ex = @"^/w+$";

              System.Text.RegularExpressions.Regex reg = new Regex( ex );                              bool flag = reg.IsMatch( str );

2.    验证邮件格式

C#

System.String ex = @"^/w+@/w+/./w+$";

System.Text.RegularExpressions.Regex reg = new Regex( ex );

bool flag = reg.IsMatch( str );

3.    更改日期的格式(用 dd-mm-yy 的日期形式代替 mm/dd/yy 的日期形式)

C#

String MDYToDMY(String input)

   {

      return Regex.Replace(input,

         "//b(?<month>//d{1,2})/(?<day>//d{1,2})/(?<year>//d{2,4})//b",

         "${day}-${month}-${year}");

   }

4.    URL 提取协议和端口号

C#

String Extension(String url)

   {

      Regex r = new Regex(@"^(?<proto>/w+)://[^/]+?(?<port>:/d+)?/",

         RegexOptions.Compiled);

      return r.Match(url).Result("${proto}${port}");

   }

这里的例子可能是我们在网页开发中,通常会碰到的一些正则表达式,尤其在第一个例子中,给出了使用javascript,vbScript,C#等不同语言的实现方式,大家不难看出,对于不同的语言来说,正则表达式没有区别,只是正则表达式的实现类不同而已。而如何发挥正则表达式的公用,也要看实现类的支持。

(摘自msdn: Microsoft .NET 框架 SDK 提供大量的正则表达式工具,使您能够高效地创建、比较和修改字符串,以及迅速地分析大量文本和数据以搜索、移除和替换文本模式。ms-help://MS.VSCC/MS.MSDNVS.2052/cpgenref/html/cpconregularexpressionslanguageelements.htm

下面我们逐个来分析这些例子:

1-2,这两个例子很简单,只是简单的验证字符串是否符合正则表达式规定的格式,其中使用的语法,在第一篇文章中都已经介绍过了,这里做一下简单的描述。

1个例子的表达式:  ^/w+$

^ -- 表示限定匹配开始于字符串的开始

         /w 表示匹配英文字符

         + -- 表示匹配字符出现1次或多次

         $ -- 表示匹配字符到字符串结尾处结束

         验证形如asgasdfs的字符串

2个例子的表达式:  ^/w+@/w+./w+$

^ -- 表示限定匹配开始于字符串的开始

/w 表示匹配英文字符

+ -- 表示匹配字符出现1次或多次

@ -- 匹配普通字符@

/. 匹配普通字符.(注意.为特殊字符,因此要加上/转译)

$ -- 表示匹配字符到字符串结尾处结束

验证形如dragontt@sina.com的邮件格式

 

 

     3 个例子中,使用了替换,因此,我们还是先来看看正则表达式中替换的定义:

ms-help://MS.VSCC/MS.MSDNVS.2052/cpgenref/html/cpconsubstitutions.htm

替换

字符

含义

$123

替换由组号 123(十进制)匹配的最后一个子字符串。

${name}

替换由 (?<name> ) 组匹配的最后一个子字符串。

$$

替换单个“$”字符。

$&

替换完全匹配本身的一个副本。

$`

替换匹配前的输入字符串的所有文本。

$'

替换匹配后的输入字符串的所有文本。

$+

替换最后捕获的组。

$_

替换整个输入字符串。

分组构造

ms-help://MS.VSCC/MS.MSDNVS.2052/cpgenref/html/cpcongroupingconstructs.htm

分组构造

定义

( )

捕获匹配的子字符串(或非捕获组;有关更多信息,请参阅正则表达式选项中的 ExplicitCapture 选项。)使用 () 的捕获根据左括号的顺序从 1 开始自动编号。捕获元素编号为零的第一个捕获是由整个正则表达式模式匹配的文本。

(?<name> )

将匹配的子字符串捕获到一个组名称或编号名称中。用于 name 的字符串不能包含任何标点符号,并且不能以数字开头。可以使用单引号替代尖括号,例如 (?'name')

(?<name1-name2> )

平衡组定义。删除先前定义的 name2 组的定义并在 name1 组中存储先前定义的 name2 组和当前组之间的间隔。如果未定义 name2 组,则匹配将回溯。由于删除 name2 的最后一个定义会显示 name2 的先前定义,因此该构造允许将 name2 组的捕获堆栈用作计数器以跟踪嵌套构造(如括号)。在此构造中,name1 是可选的。可以使用单引号替代尖括号,例如 (?'name1-name2')

(?: )

非捕获组。

(?imnsx-imnsx: )

应用或禁用子表达式中指定的选项。例如,(?i-s: ) 将打开不区分大小写并禁用单行模式。有关更多信息,请参阅正则表达式选项。

(?= )

零宽度正预测先行断言。仅当子表达式在此位置的右侧匹配时才继续匹配。例如,/w+(?=/d) 与后跟数字的单词匹配,而不与该数字匹配。此构造不会回溯。

(?! )

零宽度负预测先行断言。仅当子表达式不在此位置的右侧匹配时才继续匹配。例如,/b(?!un)/w+/b 与不以 un 开头的单词匹配。

(?<= )

零宽度正回顾后发断言。仅当子表达式在此位置的左侧匹配时才继续匹配。例如,(?<=19)99 与跟在 19 后面的 99 的实例匹配。此构造不会回溯。

(?<! )

零宽度负回顾后发断言。仅当子表达式不在此位置的左侧匹配时才继续匹配。

(?> )

非回溯子表达式(也称为贪婪子表达式)。该子表达式仅完全匹配一次,然后就不会逐段参与回溯了。(也就是说,该子表达式仅与可由该子表达式单独匹配的字符串匹配。)

 

我们还是先简单的了解一下这两个概念:

分组构造:

最基本的构造方式就是(),在左右括号中括起来的部分,就是一个分组;

更进一步的分组就是形如:(?<name> )的分组方式,这种方式与第一种方式的不同点,就是对分组的部分进行了命名,这样就可以通过该组的命名来获取信息;

(还有形如(?= )等等的分组构造,我们这篇的例子中也没有使用到,下次我们在来介绍)

替换:

       上面提到了两种基本的构造分组方式()以及(?<name> ),通过这两种分组方式,我们可以得到形如$1,${name}的匹配结果。

 

       这样说,可能概念上还是有些模糊,我们还是结合上面的例子来说:

第三个例子的正则表达式为://b(?<month>//d{1,2})/(?<day>//d{1,2})/(?<year>//d{2,4})//b

(解释一下,为什么这里都是//一起用:这里是C#的例子,在C#语言中/是转译字符,要想字符串中的/不转译,就需要使用//或者在整个字符串的开始加上@标记,即上面等价与

@/b(?<month>/d{1,2})/(?<day>/d{1,2})/(?<year>/d{2,4}/b

/b --  是一种特殊情况。在正则表达式中,除了在 [] 字符类中表示退格符以外,/b 表示字边界(在 /w 和 /W 字符之间)。在替换模式中,/b 始终表示退格符

(?<month>/d{1,2}) 构造一个名为month的分组,这个分组匹配一个长度为1-2的数字

/ -- 匹配普通的/字符

(?<day>/d{1,2}) --构造一个名为day的分组,这个分组匹配一个长度为1-2的数字

/ -- 匹配普通的/字符

(?<year>/d{2,4}/b --构造一个名为year的分组,这个分组匹配一个长度为2-4的数字

 

这里还不能够看出这些分组的作用,我们接着看这一句

${day}-${month}-${year}

${day} 获得上面构造的名为day的分组匹配后的信息

- -- 普通的-字符

${month} --获得上面构造的名为month的分组匹配后的信息

- -- 普通的-字符

${year} --获得上面构造的名为year的分组匹配后的信息

 

举例来说:

将形如04/02/2003的日期使用例3种的方法替换

(?<month>/d{1,2}) 分组将匹配到04由${month}得到这个匹配值

(?<day>/d{1,2}) 分组将匹配到02由${day}得到这个匹配值

(?<year>/d{1,2}) 分组将匹配到2003由${year}得到这个匹配值

了解了这个例子后,我们在来看第4个例子就很简单了。

 

4个例子的正则

^(?<proto>/w+)://[^/]+?(?<port>:/d+)?/

^ -- 表示限定匹配开始于字符串的开始

(?<proto>/w+) 构造一个名为proto的分组,匹配一个或多个字母

: -- 普通的:字符

// -- 匹配两个/字符

[^/] 表示这里不允许是/字符

+? 表示指定尽可能少地使用重复但至少使用一次匹配

(?<port>:/d+) 构造一个名为port的分组,匹配形如:2134(冒号+一个或多个数字)

? 表示匹配字符出现0次或1次

/ -- 匹配/字符

 

最后通过${proto}${port}来获取两个分组构造的匹配内容

(有关Regex对象的用法,参考

ms-help://MS.VSCC/MS.MSDNVS.2052/cpref/html/frlrfSystemTextRegularExpressionsRegexMembersTopic.htm

 

好了,本次介绍的几个例子,也讲得差不多了,希望大家有所收获,下次,在就一些特殊的要求,进一步探讨正则表达式的实现。

阅读全文
0 0

相关文章推荐

img
取 消
img