当前位置:编程学习 > C#/ASP.NET >>

正则表达式实例分解

趁有空发个贴子,

数学公式正则表达式:
(?'kh'\()*([\-\+]){0,1}[0-9\.]+(?'-kh'\))*([\+\-\*\/]{1}(?'kh'\()*((?<=\()([\-\+]){0,1})?[0-9\.]+(?'-kh'\))*)+(?('kh')(?!))

匹配加减乘除数学公式,如:((1+2)-3*4)

(?'kh'\()*([\-\+]){0,1}[0-9\.]+(?'-kh'\))*([\+\-\*\/]{1}(?'kh'\()*((?<=\()([\-\+]){0,1})?[0-9\.]+(?'-kh'\))*)+(?('kh')(?!))
可以"("开始,压入堆栈统计括号数量,*代表可以出现0次或多次

(?'kh'\()*([\-\+]){0,1}[0-9\.]+(?'-kh'\))*([\+\-\*\/]{1}(?'kh'\()*((?<=\()([\-\+]){0,1})?[0-9\.]+(?'-kh'\))*)+(?('kh')(?!))
可以出现一次正负号

(?'kh'\()*([\-\+]){0,1}[0-9\.]+(?'-kh'\))*([\+\-\*\/]{1}(?'kh'\()*((?<=\()([\-\+]){0,1})?[0-9\.]+(?'-kh'\))*)+(?('kh')(?!))
0-9数字,一个或多个

(?'kh'\()*([\-\+]){0,1}[0-9\.]+(?'-kh'\))*([\+\-\*\/]{1}(?'kh'\()*((?<=\()([\-\+]){0,1})?[0-9\.]+(?'-kh'\))*)+(?('kh')(?!))
可以")"结束,弹出堆栈统计括号数量,*代表可以出现0次或多次

(?'kh'\()*([\-\+]){0,1}[0-9\.]+(?'-kh'\))*([\+\-\*\/]{1}(?'kh'\()*((?<=\()([\-\+]){0,1})?[0-9\.]+(?'-kh'\))*)+(?('kh')(?!))
橙色括号分组说明可以出现一次或多次,如公式1+2 ,这个括号里是匹配 2
红色要求+-*/出现一次

(?'kh'\()*([\-\+]){0,1}[0-9\.]+(?'-kh'\))*([\+\-\*\/]{1}(?'kh'\()*((?<=\()([\-\+]){0,1})?[0-9\.]+(?'-kh'\))*)+(?('kh')(?!))
判断括号开始时,可以有正负号,?代表使用懒惰匹配,即如:1+(((2-3)+4)+5)时,只匹配数字2前面的一个括号一次

(?'kh'\()*([\-\+]){0,1}[0-9\.]+(?'-kh'\))*([\+\-\*\/]{1}(?'kh'\()*((?<=\()([\-\+]){0,1})?[0-9\.]+(?'-kh'\))*)+(?('kh')(?!))
检查括号是否配对
--------------------编程问答-------------------- 技术贴。 --------------------编程问答-------------------- 整理的一个参考资料:

元字符 代码 说明 
. 匹配除换行符以外的任意字符 
\w 匹配字母或数字或下划线或汉字 
\s 匹配任意的空白符 
\d 匹配数字 
\b 匹配单词的开始或结束 
^ 匹配字符串的开始 
$ 匹配字符串的结束 

字符转义
这时你就必须使用\来取消这些字符的特殊意义。因此,你应该使用\.和\*。当然,要查找\本身,你也得用\\.

重复 代码/语法 说明 
* 重复零次或更多次 
+ 重复一次或更多次 
? 重复零次或一次 
{n} 重复n次 
{n,} 重复n次或更多次 
{n,m} 重复n到m次 

字符类
我们也可以轻松地指定一个字符范围,像[0-9]代表的含意与\d就是完全一致的:一位数字,同理[a-z0-9A-Z_]也完全等同于\w(如果只考虑英文的话)。

反义 代码/语法 说明 
\W 匹配任意不是字母,数字,下划线,汉字的字符 
\S 匹配任意不是空白符的字符 
\D 匹配任意非数字的字符 
\B 匹配不是单词开头或结束的位置 
[^x] 匹配除了x以外的任意字符 
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符 

替换
正则表达式里的替换指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。

分组
我们已经提到了怎么重复单个字符(直接在字符后面加上限定符就行了);但如果想要重复多个字符又该怎么办?你可以用小括号来指定子表达式(也叫做分组),然后你就可以指定这个子表达式的重复次数了,你也可以对子表达式进行其它一些操作(后面会有介绍)。

后向引用
使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2
后向引用用于重复搜索前面某个分组匹配的文本。例如,\1代表分组1匹配的文本。

捕获 
(exp) 匹配exp,并捕获文本到自动命名的组里 
(?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp) 
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号 

零宽断言 
(?=exp) 匹配exp前面的位置 
(?<=exp) 匹配exp后面的位置 
(?!exp) 匹配后面跟的不是exp的位置 
(?<!exp) 匹配前面不是exp的位置 
注释 
(?#comment) 这种类型的组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 

零宽断言
(?=exp)也叫零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp。比如\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.时,它会匹配sing和danc。
(?<=exp)也叫零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式exp。比如(?<=\bre)\w+\b会匹配以re开头的单词的后半部分(除了re以外的部分),例如在查找reading a book时,它匹配ading。

负向零宽断言
零宽度负预测先行断言(?!exp),断言此位置的后面不能匹配表达式exp。例如:\d{3}(?!\d)匹配三位数字,而且这三位数字的后面不能是数字;\b((?!abc)\w)+\b匹配不包含连续字符串abc的单词。
同理,我们可以用(?<!exp),零宽度正回顾后发断言来断言此位置的前面不能匹配表达式exp:(?<![a-z])\d{7}匹配前面不是小写字母的七位数字。

表5.懒惰限定符 
*? 重复任意次,但尽可能少重复 
+? 重复1次或更多次,但尽可能少重复 
?? 重复0次或1次,但尽可能少重复 
{n,m}? 重复n到m次,但尽可能少重复 
{n,}? 重复n次以上,但尽可能少重复 

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

平衡组/递归匹配
(?'group') 把捕获的内容命名为group,并压入堆栈 
(?'-group') 从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败 
(?(group)yes|no) 如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分 
(?!) 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败

语法
\a 报警字符(打印它的效果是电脑嘀一声) 
\b 通常是单词分界位置,但如果在字符类里使用代表退格 
\t 制表符,Tab 
\r 回车 
\v 竖向制表符 
\f 换页符 
\n 换行符 
\e Escape 
\0nn ASCII代码中八进制代码为nn的字符 
\xnn ASCII代码中十六进制代码为nn的字符 
\unnnn Unicode代码中十六进制代码为nnnn的字符 
\cN ASCII控制字符。比如\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
--------------------编程问答-------------------- 个人应用实例:

抓取网页代码中的标题:
(?<=<\s*\btitle\b[^>]*>)(.*)(?=<\s*/\btitle\b[^>]*>)

抓取网页代码中的关键字:
一,取出<meta keyword=....> :<\s*\bmeta\b[^>]*\bkeyword[^>]*>
二,取出content的值: \bcontent\b(\s)*=(\s)*([" + "\"']?)(.*)\3抓
\3是分组引用

取网页代码中的链接:
(?<=(<\s*\ba\b[^>]*\bhref\b(\s)?=))\s*(((" + "\"){1}([^" + "\"]*)(" + "\"){1})|(('){1}([^']*)('){1})|([^ >" + "\"']+[^ >]?))


--------------------编程问答-------------------- mark,
卖咖啡
卖瓜子
卖板凳
坐下学习 --------------------编程问答-------------------- 我还是拿杯茶喝下 --------------------编程问答-------------------- 关注学习 很好很强大.. --------------------编程问答-------------------- 这个得顶。 --------------------编程问答-------------------- --------------------编程问答-------------------- 技术贴...学习 --------------------编程问答-------------------- jinlaixueji --------------------编程问答-------------------- mark.... --------------------编程问答-------------------- --------------------编程问答-------------------- 路过,接分。 --------------------编程问答--------------------








论坛签名======================================================================

CrazyFor:你好!
截至 2011-03-31 09:53:11 前:
你已发帖 195 个, 未结贴 0 个;
结贴率为: 100.00%
--------------------编程问答-------------------- 学习了 ,多几个实用例子,更容易理解 --------------------编程问答-------------------- 学习 学习 --------------------编程问答-------------------- 收藏了! --------------------编程问答-------------------- 技术贴,学习了。 --------------------编程问答-------------------- 正则表达式看得真累! --------------------编程问答-------------------- 看看! --------------------编程问答-------------------- 正则表达式看起来就很难 --------------------编程问答-------------------- --------------------编程问答--------------------
瞄一眼。。。 --------------------编程问答-------------------- 平衡组老是参不透。。。 --------------------编程问答-------------------- 有鸭梨,学习学习 --------------------编程问答-------------------- 路过。。学习。。蹭分 --------------------编程问答-------------------- 好帖子 --------------------编程问答-------------------- 感谢楼主,正需要呢! --------------------编程问答-------------------- 收藏学习了 --------------------编程问答-------------------- 路过。。学习。。蹭分 --------------------编程问答-------------------- 学习下 --------------------编程问答-------------------- mark up --------------------编程问答-------------------- 10分贴。。接分。 --------------------编程问答--------------------   正则 好东东啊。。 --------------------编程问答-------------------- 不错,学习 --------------------编程问答-------------------- 学习了 --------------------编程问答-------------------- 学习... --------------------编程问答-------------------- 好贴! --------------------编程问答-------------------- 学习! --------------------编程问答-------------------- 涉及不限定层次的嵌套,那这里应该使用了 .net 中的平衡组,呵呵。

不过对于数学公式之类的检查是否有效,我个人是不建议使用正则表达式来判断,应该使用语法、词法工具来做,呵呵。

当然了,如果是为了学习正则表达式,这样的是非常好地练习。 --------------------编程问答-------------------- 那个家伙要是被指派去调试这堆东西。。。估计马上抓狂。。 --------------------编程问答-------------------- 学习学习 --------------------编程问答-------------------- 好帖呀 --------------------编程问答-------------------- 强,这分明就是技术贴 --------------------编程问答-------------------- 貌似刚从phpchina上看到,难道是同一个人? --------------------编程问答--------------------
引用 45 楼 ftruth 的回复:
貌似刚从phpchina上看到,难道是同一个人?


没有在其它地方发过,难道被盗版,嘿嘿~~
--------------------编程问答-------------------- 收藏了 --------------------编程问答-------------------- 很有用的,我收藏了 --------------------编程问答-------------------- --------------------编程问答--------------------   --------------------编程问答-------------------- 好帖子 --------------------编程问答-------------------- 哈哈 不错 --------------------编程问答-------------------- 哈哈,强势顶起! --------------------编程问答-------------------- 技术贴,顶 --------------------编程问答-------------------- --------------------编程问答-------------------- 很好的东西收藏了! --------------------编程问答-------------------- 难但是学会了很强大
--------------------编程问答-------------------- 这个在java上都通用不? --------------------编程问答-------------------- hao yun --------------------编程问答-------------------- 谢分享 --------------------编程问答-------------------- 鸭梨很大。。 --------------------编程问答-------------------- 谢谢~~ --------------------编程问答--------------------
引用 58 楼 super_thinker 的回复:
这个在java上都通用不?


不能,这其中涉及平衡组的语法,Java 目前版本还不支持。 --------------------编程问答-------------------- 这个好,顶一下~ --------------------编程问答-------------------- 学会了,可以去做动态采集了…… --------------------编程问答-------------------- 学习了 --------------------编程问答-------------------- 正则 很强大 --------------------编程问答-------------------- 强悍 我看得都晕~ --------------------编程问答-------------------- 好贴!!! --------------------编程问答-------------------- 看着眼晕,呵呵 --------------------编程问答-------------------- 我也来MARK --------------------编程问答--------------------
引用 40 楼 bao110908 的回复:
不过对于数学公式之类的检查是否有效,我个人是不建议使用正则表达式来判断,应该使用语法、词法工具来做,呵呵。

当然了,如果是为了学习正则表达式,这样的是非常好地练习。

我也同意火龙果的观点

其实楼主这个正则,还有很多值得商榷的地方,简单说几点,欢迎讨论
目的是验证还是提取,无论是哪一种,用下面的字符串试下
(1+2
看看结果是什么,个人觉得分析结果为什么是这样,远比研究如何写这个正则有意思,当然,也更伤脑细胞

还有
([\-\+]){0,1})? 这里的{0,1}与后面的“?”作用是相同的,正则本身就很晦涩,同一正则中,出现多种写法,会进一步降低可读性
{1} 在正则中出现是让人很无奈的一件事
还有个别地方的捕获组用得没有道理的

引用 33 楼 wuyazhe 的回复:
10分贴。。接分。

无牙不敬业,看了也不研究,只来打酱油


个人比较喜欢研究正则的原理及应用,只可惜现在留给正则的时间是越来越少了 --------------------编程问答-------------------- up to you --------------------编程问答--------------------
引用 72 楼 lxcnn 的回复:
引用 40 楼 bao110908 的回复:
不过对于数学公式之类的检查是否有效,我个人是不建议使用正则表达式来判断,应该使用语法、词法工具来做,呵呵。

当然了,如果是为了学习正则表达式,这样的是非常好地练习。

我也同意火龙果的观点

其实楼主这个正则,还有很多值得商榷的地方,简单说几点,欢迎讨论
目的是验证还是提取,无论是哪一种,用下面的字符串试下
(1+2
看看结果是什……



多谢lxcnn指点,更正了括号配对问题和语法混淆问题。

(?'kh'\()*([\-\+])?[0-9\.]+(?'-kh'\))*([\+\-\*\/]{1}(?'kh'\()*((?<=\()([\-\+])?)?[0-9\.]+(?'-kh'\))*)+(?(kh)(?!)) --------------------编程问答-------------------- 我用于测试的数学公式:((1+(-100+(1*2-(91+(2-3+4)+100)-10*10)-(-100)))*7

可能还是会有bug的,天知道呢,呵呵~~~ --------------------编程问答-------------------- 之前的忘了删除字符串相加的一些字符

抓取网页代码中的关键字:
一,取出<meta keyword=....> :<\s*\bmeta\b[^>]*\bkeyword[^>]*>
二,取出content的值: \bcontent\b(\s)*=(\s)*([" + "\"']?)(.*)\3 
更正为:\bcontent\b(\s)*=(\s)*([\"']?)(.*)\3

\3是分组引用

取网页代码中的链接:
(?<=(<\s*\ba\b[^>]*\bhref\b(\s)?=))\s*(((" + "\"){1}([^" + "\"]*)(" + "\"){1})|(('){1}([^']*)('){1})|([^ >" + "\"']+[^ >]?))
更正为:(?<=(<\s*\ba\b[^>]*\bhref\b(\s)?=))\s*(((\"){1}([^\"]*)(\"){1})|(('){1}([^']*)('){1})|([^ >\"']+[^ >]?))

--------------------编程问答-------------------- 看了头晕 --------------------编程问答-------------------- UP~~~~~~~~~ --------------------编程问答-------------------- 有用,得学学 --------------------编程问答-------------------- 很给力 非常强悍 定一个 --------------------编程问答-------------------- 开始看介绍还好,但一实践就完全 不会了 --------------------编程问答-------------------- 技术贴,学习了。 --------------------编程问答-------------------- 没有看懂 --------------------编程问答-------------------- 测试了下 不对怎么破啊~
补充:.NET技术 ,  非技术区
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,