正则表达式30分钟入门教程(7)

作者:deerchao 来源:unibetter大学生社区 时间:2007-08-27 10:38:00 

处理选项

上面介绍了几个选项如忽略大小写,处理多行等,这些选项能用来改变处理正则表达式的方式。下面是.Net中常用的正则表达式选项:


表6.常用的处理选项
名称说明
IgnoreCase(忽略大小写)匹配时不区分大小写。
Multiline(多行模式)更改^和$的含义,使它们分别在任意一行的行首和行尾匹配,而不仅仅在整个字符串的开头和结尾匹配。(在此模式下,$的精确含意是:匹配\n之前的位置以及字符串结束前的位置.)
Singleline(单行模式)更改.的含义,使它与每一个字符匹配(包括换行符\n)。
IgnorePatternWhitespace(忽略空白)忽略表达式中的非转义空白并启用由#标记的注释。
RightToLeft(从右向左查找)匹配从右向左而不是从左向右进行。
ExplicitCapture(显式捕获)仅捕获已被显式命名的组。
ECMAScript(JavaScript兼容模式)使表达式的行为与它在JavaScript里的行为一致。


一个经常被问到的问题是:是不是只能同时使用多行模式和单行模式中的一种?答案是:不是。这两个选项之间没有任何关系,除了它们的名字比较相似(以至于让人感到疑惑)以外。

平衡组/递归匹配

注意:这里介绍的平衡组语法是由.Net Framework支持的;其它语言/库不一定支持这种功能,或者支持此功能但需要使用不同的语法。

有时我们需要匹配像( 100 * ( 50 + 15 ) )这样的可嵌套的层次性结构,这时简单地使用\(.+\)则只会匹配到最左边的左括号和最右边的右括号之间的内容(这里我们讨论的是贪婪模式,懒惰模式也有下面的问题)。假如原来的字符串里的左括号和右括号出现的次数不相等,比如( 5 / ( 3 + 2 ) ) ),那我们的匹配结果里两者的个数也不会相等。有没有办法在这样的字符串里匹配到最长的,配对的括号之间的内容呢?

为了避免(和\(把你的大脑彻底搞糊涂,我们还是用尖括号代替圆括号吧。现在我们的问题变成了如何把xx <aa <bbb> <bbb> aa> yy这样的字符串里,最长的配对的尖括号内的内容捕获出来?

这里需要用到以下的语法构造:

  • (?’group’) 把捕获的内容命名为group,并压入堆栈

  • (?’-group’) 从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败

  • (?(group)yes|no) 如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分

  • (?!) 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败

如果你不是一个程序员(或者你是一个对堆栈的概念不熟的程序员),你就这样理解上面的三种语法吧:第一个就是在黑板上写一个 "group",第二个就是从黑板上擦掉一个"group",第三个就是看黑板上写的还有没有"group",如果有就继续匹配yes部分,否则就匹配 no部分。

我们需要做的是每碰到了左括号,就在黑板上写一个"group",每碰到一个右括号,就擦掉一个,到了最后就看看黑板上还有没有--如果有那就证明左括号比右括号多,那匹配就应该失败。


<                         #最外层的左括号  
    [^<>]*                #最外层的左括号后面的不是括号的内容  
    (  
        (  
            (?’Open’<)    #碰到了左括号,在黑板上写一个"Open"  
            [^<>]*       #匹配左括号后面的不是括号的内容  
        )+  
        (  
            (?’-Open’>)   #碰到了右括号,擦掉一个"Open"  
            [^<>]*        #匹配右括号后面不是括号的内容  
        )+  
    )*  
    (?(Open)(?!))         #在遇到最外层的右括号前面,判断黑板上还有没有没擦掉的"Open";如果还有,则匹配失败  
>                         #最外层的右括号


平衡组的一个最常见的应用就是匹配HTML,下面这个例子可以匹配嵌套的<div>标签:<div[^>]*>[^<>]*(((?’Open’<div[^>]*>)[^<>]*)+((?’-Open’</div>)[^<>]*)+)*(?(Open)(?!))</div>.

还有些什么东西没提到

我已经描述了构造正则表达式的大量元素,还有一些我没有提到的东西。下面是未提到的元素的列表,包含语法和简单的说明。你可以在网上找到更详细的参考资料来学习它们--当你需要用到它们的时候。如果你安装了MSDN Library,你也可以在里面找到关于.net下正则表达式详细的文档。


表7.尚未详细讨论的语法
\a报警字符(打印它的效果是电脑嘀一声)
\b通常是单词分界位置,但如果在字符类里使用代表退格
\t制表符,Tab
\r回车
\v竖向制表符
\f换页符
\n换行符
\eEscape
\0nnASCII代码中八进制代码为nn的字符
\xnnASCII代码中十六进制代码为nn的字符
\unnnnUnicode代码中十六进制代码为nnnn的字符
\cNASCII控制字符。比如\cC代表Ctrl+C
\A字符串开头(类似^,但不受处理多行选项的影响)
\Z字符串结尾或行尾(不受处理多行选项的影响)
\z字符串结尾(类似$,但不受处理多行选项的影响)
\G当前搜索的开头
\p{name}Unicode中命名为name的字符类,例如\p{IsGreek}
(?>exp)贪婪子表达式
(?<x>-<y>exp)平衡组
(?im-nsx:exp)在子表达式exp中改变处理选项
(?im-nsx)为表达式后面的部分改变处理选项
(?(exp)yes|no)把exp当作零宽正向先行断言,如果在这个位置能匹配,使用yes作为此组的表达式;否则使用no
(?(exp)yes)同上,只是使用空表达式作为no
(?(name)yes|no)如果命名为name的组捕获到了内容,使用yes作为表达式;否则使用no
(?(name)yes)同上,只是使用空表达式作为no


联系作者

好吧,我承认,我骗了你,读到这里你肯定花了不止30分钟.相信我,这是我的错,而不是因为你太笨.我之所以说"30分钟",是为了让你有信心,有耐心继续下去.既然你看到了这里,那证明我的阴谋成功了.上这种当的滋味还不错吧?

要投诉我,或者觉得我其实可以做得更好,或者有任何其它问题,欢迎来我的博客进行讨论.

一些我认为你可能已经知道的术语的参考

  • 字符

  • 程序处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等等。

  • 字符串

  • 0个或更多个字符的序列。

  • 文本

  • 文字,字符串。

  • 匹配

  • 符合规则,检验是否符合规则,符合规则的部分。

  • 断言

  • 声明一个应该为真的事实。只有当断言为真时才会对正则表达式继续进行匹配。

网上的资源及本文参考文献

更新说明

  1. 2006-3-27 第一版

  2. 2006-10-12 第二版

    • 修正了几个细节上的错误和不准确的地方

    • 增加了对处理中文时的一些说明

    • 更改了几个术语的翻译(采用了MSDN的翻译方式)

    • 增加了平衡组的介绍

    • 放弃了对The Regulator的介绍,改用Regex Tester

  3. 2007-3-12 V2.1

    • 修正了几个小的错误

    • 增加了对处理选项(RegexOptions)的介绍

  4. 2007-5-28 V2.2

    • 重新组织了对零宽断言的介绍

    • 删除了几个不太合适的示例,添加了几个实用的示例

    • 其它一些微小的更改

  5. 2007-8-3 V2.21

    • 修改了几处文字错误

    • 修改/添加了对$,\b的精确说明

    • 承认了作者是个骗子

    • 给RegexTester添加了Singleline选项的相关功能

版本:v2.21 (2007-8-3) 作者:deerchao 来源:unibetter大学生社区

标签:正则表达式,入门
0
投稿

猜你喜欢

  • 如何把数据从SQL Server导出到Access或Excel中去?

    2009-11-02 20:26:00
  • css清除浮动的方法总结与选择

    2008-06-06 12:58:00
  • JavaScript入门学习书籍的阶段选择

    2008-01-11 19:39:00
  • MySQL的数据库常用命令 超级实用版分享

    2012-01-05 18:58:00
  • 函数式编程让JS更优美

    2008-06-10 12:40:00
  • mssql server 数据库附加不上解决办法分享

    2011-09-30 11:55:20
  • 新浪乐居的人不好!哈哈

    2009-07-23 20:39:00
  • 读写xml文件的2个小函数

    2007-08-23 12:59:00
  • 错误的随机数_JavaScript

    2009-08-28 12:43:00
  • 什么是响应式Web设计?怎样进行?

    2011-11-21 17:00:40
  • 谈非线性任务流程的窗口打开方式

    2008-08-28 12:47:00
  • javascript面向对象技术基础(三)

    2010-02-07 13:11:00
  • asp程序定义变量比不定义变量速度快一倍

    2012-12-04 20:06:32
  • MySQL高级查询方法之记录查询

    2010-06-20 14:48:00
  • CSS nuggets CSS金矿

    2009-10-28 18:59:00
  • ASP:Cookie使用指南

    2007-09-28 12:48:00
  • Script 元素 type 属性的妙用

    2011-03-07 16:13:00
  • Mootools 1.2教程(12)——用Drag.Move实现拖拽和拖放

    2008-12-05 12:29:00
  • 动态给表添加删除字段并同时修改它的插入更新存储过程

    2011-12-01 10:18:28
  • ASP中实现分页显示的七种方法

    2007-09-20 13:19:00
  • asp之家 网络编程 m.aspxhome.com