newuser 发表于 2011-1-7 13:36:56

正则笔记

#cs
正则学习笔记---感谢deercao和所有的正则资料提供者

1、正则基础知识
正则表达式就是个字符(串)处理语言,是用来“查找匹配的字符串和对匹配的字符串进行替换“。
正则表达式是由”元字符和普通字符“组成。普通字符由“字母 数字 汉字 下划线以及没有特殊意义的标点符号”组成;元字符由诸如
\d\w.* + 等有特殊意义的符号组成。
网页、程序或文件中有关文本内容的处理部分都可以应用正则表达式完成。
在正则表达式中,元字符有特殊功能,如\w匹配“数字、字母、下划线、汉字”,这个在afan的正则表达式工具中有详细说明。

占有字符和零宽度的概念: 例 stringregexp(字符串,"正则表达式模式")
如果”正则表达式模式匹配了“字符串中的内容”并且匹配的内容被保存到匹配结果中,就说明“正则表达式模式”是------占有字符
如果”正则表达式模式"只是匹配位置或其匹配的内容没有被保存到匹配结果中,就说明“正则表达式模式”是------零宽度

占有字符互斥:一个字符同一时间只能由一个“正则表达式模式”匹配
零宽度非互斥:一个位置同一时间可由多个“正则表达式模式”匹配

2、字符分类:用[]括起来的就是一个字符分类,无论[]有多少个字符,同一时间只能匹配[]中的某一个字符。
         元字符在[]中失去原有意义,只能作为一个普通的文本字符,注意\ ^ - : []在[]里还是元字符,即保留其特殊意义。
               
               在[]里是区分大小写的。如"abc"用只能匹配出 b c,用(?i)能匹配出 a b c .
               
               - 不是元字符,例[-0-9]前一个 - 是一个普通字符,匹配本身,0-9中的-表示范围,相当于       
      如匹配 a 或 e 或 u   , [.?!] 匹配 .   或   ?或! ,此刻的字符类里的元字符就
      不代表特殊的含义了。
                [^a1<]表示除“a”、“1”、“<”外的其它任意一个字符
                ([^\r]+) 我以前理解为”排除回车符号的至少一个什么字符的匹配“不如”匹配一个及以上非回车的字符“好理解,而且要注意其中
                ()的适用场景,用不用他效果有时差别真的很大!
                “<[^>]*>”中“[^>]*”表示0个或任意多个不是“>”的字符
                [\u4e00-\u9fa5] 匹配汉字?AUTOIT不支持吗?

3、分支结构(Alternation):   用 |表示,就是多条件匹配
    如用 \d{3}-\d{7}|\d{7} 匹配010-1234556或1234556,但注意别写成 \d{7}|\d{3}-\d{7},因为它只能匹配连续的7位数字或
        3位数字-7位数字中的前7位了,我的理解是“在进行多条件匹配时,要把最大的匹配范围写到最前面,然后依次减小匹配范围”
       
4、分组 :用() 括起来就是一个分组,用()标记“子表达式的开始和结束”

    重点掌握:捕获与非捕获
        用()将正则表达式模式括起来,那么正则表达式模式匹配的内容会被捕获,那如果不想捕获,可以使用 ?:   ?!?= 非捕获标志
        例:想捕获 this 和 thas
        Local $str="At this point the remaining pattern matches, so thas is the match returned"
        Local $result=StringRegExp($str,"th(i|a)s",3) 因为用了(),所以i|a匹配的内容被捕获,结果显示的结果是 i a,不是 this thas
    Local $result=StringRegExp($str,"th(?:i|a)s",3) 用了 ?: ,(i|a)匹配的内容不捕获,最后显示的匹配结果就是想要的 this thas
    _ArrayDisplay($result)

   如用于IP地址的匹配模式(\d{1,3}\.){3}\d{1,3},分组()里的内容意思是”匹配1-3位的数字后面跟个.的形式重复3次,
       最后再跟1个1-3位的数字。
        分组还可以后向引用 ,对此部分要加强理解,看 example9 示例
        分组号是从 1 、2 逐次命名的,\0代表“整个正则表达式匹配的内容”。
        组名可用(?<GroupName>)定义,如(\d{1,3}\.){3}\d{1,3}中的组可(?<Group1>\d{3}\.)定义,引用则用\k<Group1>,完整语法为
        (?<Group1>\d{3}\.){3}\k<Group1> ,其中的 < >可用单引号 '' 替换,则变成了 (?'Group1'\d{3}\.){3}\k'Group1'.
        注意:对于组的组号分配 是先从未定义的组开始分配组号,然后才对定义的组进行组号分配,所以已定义的组的组号一定大于未定义组的组号
   
        分组的3种语法:前2中语法称作“捕获组”,第3种称作“非捕获组”,也好理解,就看是否有“组”生成
    (exp)   匹配exp,并捕获文本到自动分配组号的组里
        (?<GroupName>exp)匹配exp,并捕获文本到 自定义的<GroupName>组里
        组的反向应用一定是应用在以上的捕获组里,因为必须有
       
        (?:exp)匹配exp,但不给组分配组号,也不捕获文本到组里,但它将捕获的内容保存到最终的整个表达式的匹配结果中
       
5、零宽断言(也有称作环视---Look Around) :
    (?=exp)   匹配exp前面的内容
        (?<=exp)匹配exp后面的内容
        (?!exp)   所在位置右侧不能匹配exp表达式---我之前的错误理解:可以看成 Str(?!exp),就是Str后不匹配exp
        (?<!exp)所在位置左侧不能匹配exp表达式---我之前的错误理解:可以看成(?<!exp)Str,就是Str前不匹配exp
       
        注意:环视是零宽度的,即匹配的内容不保存到最终的匹配结果中
       
6、注释:语法为 (?#comments)
    例 2\d(?#200-249)|25(?#250-255)|?\d\d?(?#0-199)。

7、懒惰匹配和贪婪匹配      例用 a.*b匹配aabab
        贪婪模式是最大匹配模式,a.*b匹配以a开头以b结尾中间有任意数量字符的单词,则贪婪匹配整个字符串aabab而不是aab或ab
        懒惰模式是在保证成功匹配的情况下进行最小匹配,a.*?b则匹配aab(第1至第3个字母)和ab(第4至第5个字母)
        为什么懒惰模式不是匹配 ab(第2至第3个字母),因最先匹配优于贪婪和懒惰匹配模式,懒惰模式下该例最先匹配aab,然后是 ab(第4至第5个字母)
    懒惰模式的几种常用语法
       *? 重复任意次,但尽可能少重复
   +? 重复1次或更多次,但尽可能少重复
   ?? 重复0次或1次,但尽可能少重复
   {n,m}? 重复n到m次,但尽可能少重复
   {n,}? 重复n次以上,但尽可能少重复
       
       补充理解:限定符说明

        {m, n}?    表达式尽量只匹配m次,最多重复n次。
    {m, }?   表达式尽量只匹配m次,最多可以匹配任意次。
    ??         表达式尽量不匹配,最多匹配1次,相当于 {0, 1}?
    +?         表达式尽量只匹配1次,最多可匹配任意次,相当于 {1, }?
    *?         表达式尽量不匹配,最多可匹配任意次,相当于 {0, }?
   “占有模式”限定符:
在限定符之后添加加号(+),则使限定符成为“占有模式”。占有模式的限定符,总是尽可能多的匹配。与“贪婪模式”不同的是,即使之后的表达式匹配失败,“占有模式”也不会“让出”自己能够匹配的字符。
限定符说明
    {m, n}+      表达式尽可能重复n次,至少重复m次。
    {m, }+       表达式尽可能的多匹配,至少重复m次。
    ?+         表达式尽可能匹配1次,也可以不匹配,相当于 {0, 1}+
    ++         表达式尽可能的多匹配,至少匹配1次,相当于 {1, }+
    *+         表达式尽可能的多匹配,最少可以不匹配,相当于 {0, }+

8、量词(Quantifier) 或称"匹配次数限定符" :匹配量词前面子表达式(我喜欢把它称作正则表达式模式)的次数。
        通常量词是贪婪匹配,如用\d{4,5}字符串123456789,先看匹配5位数字的情况,没有再看4位数字的匹配情况,匹配的结果:12345 6789
        在量词后加?,则变成懒惰模式,上例的匹配结果:1234 5678,注意贪婪模式和懒惰模式的例子
       
       
9、定位符:用来描述字符串或单词的边界,如 ^$\b,注意不能对"定位符使用量词或限定符"

10、平衡组和递归匹配---根本没读懂?如果朋友有这方面的AUTOIT应用的例子,请提供!

技巧:
1 匹配所有字符[\s\S]   或   .(?s)
2 匹配邮件      \w+(?:[-+.]\w+)*@\w+(?:[-.]\w+)*\.\w+([-.]\w+)*               
3 \cx         匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
4 \Q...\E   以\Q开始以\E结尾,可将中间的字符转义为普通字符,如 \Q.+\E可以将中间的.+转义为普通字符



曾经犯过的错误:
1。对于元字符匹配的是”字符位置数量“理解混乱;

示例目录
;example1匹配数字
;example2匹配单词或汉字
;example3以下是对 ^的排除功能进行练习------------------------------------重点掌握
;example4   零宽断言4种语法的例子
;example5   零宽断言的4种语法练习
;examplp6懒惰和贪婪模式,理解并不容易
;example7对[]加深理解,无论[]里有多少个字符,都只匹配其中的一个字符,没有匹配时,就可以匹配“空格, "等字符
;example8|   分支结构学习,通常用(|)来限定分支匹配范围,如果没有(),那么|作用范围就是 | 两侧整体
;example9捕获组的反向引用的练习
;example10非捕获组(?:exp)的练习
;example11匹配”用户名 口令 URL email"练习
;example12   匹配网页源码的相关内容
#ce

;example1匹配数字
#include <array.au3>
Local $Str="我想匹配出字符串中的数字部分," & @CRLF & _
                   "第1个数字:4869579" & @CRLF & _
         "第1个数字:010-4869579" & @CRLF & _
                   "第2个数字:0201-48695795" & @CRLF & _
                   "第2个数字:(010)-4895795" & @CRLF & _
                   "第2个数字:010)-4895795" & @CRLF & _
                   "第2个数字:(0201)-48695795" & @CRLF & _
                   "第3个数字:230604198001025771" & @CRLF & _
                   "第4个数字:23060419800102577A" & @CRLF & _
                   "第4个数字:23060419800102577X" & @CRLF & _
                   "第5个数字:230604198001026" & @CRLF & _
                   "第6个数字:177608" & @CRLF & _
                   "第7个数字:2010年12月17日"
Local$Result=StringRegExp($Str,"\b\d{3}-\d{7}\b|\b\d{7}\b",3);注意多条件书写的顺序,由左及右:大范围->小范围
_ArrayDisplay($Result) ;OK
Local$Result=StringRegExp($Str,"\d{3}-\d{7}|\d{4}-\d{8}",3)
_ArrayDisplay($Result) ;OK
Local$Result=StringRegExp($Str,"\(?0\d{2}[) -]?\d{8}",3);匹配结果不好!
_ArrayDisplay($Result)
Local$Result=StringRegExp($Str,"\(0\d{2}\)[-]?\d{7}|\(0\d{3}\)[-]?\d{8}",3);匹配结果不好!
_ArrayDisplay($Result)
Local$Result=StringRegExp($Str,"\d{17}[\d|X]|\d{15}",3)
;问题:23060419800102577a,只匹配前15位数字,难道是第一个条件\d{17}[\d|X]不匹配就用\d{15},结果显示其匹配的结果?结果是这样的。
;X,还以为是个元字符,有什么特殊含义!就是一个普通的匹配字符,匹配X ,想多了!
_ArrayDisplay($Result) ;OK
Local $Result=StringRegExp($Str,"\b\d{5}\b",3)
;Local $Result=StringRegExp($Str,"[^\d]\d{5}$");条条大路通罗马,感谢lpxx
;Local $Result=StringRegExp($Str,"\d{5}",3) 这个提取不精确,只要是连续的6位数字它都匹配
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,"\d{4}[年|\-|\.]\d{1,2}[月|\-|\.]\d{1,2}日",3)
_ArrayDisplay($Result)

;example2匹配单词或汉字
Local $Str="HI hi,I'm a newuser for autoit,his name is zgk!please 多多指教,邹国奎英语实在是说不过去,ahiha!"
Local $Result=StringRegExp($Str,"hi",3);提取hi不精确
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,"\bhi\b",3);提取hi精确,区分大小写
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,"\b(?i)hi\b",3);(?i)表示不区分大小写,这样HI也可以匹配了,(?-i)表示区分大小写
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,"邹国奎",3)
_ArrayDisplay($Result)

;example3以下是对 ^的排除功能进行练习------------------------------------重点掌握
Local $Num="192.168.1.10"
Local $Result=StringRegExp($Num,'[^.]+',3)
;Local $Result=StringRegExp($Num,'[^.]*',3)
_ArrayDisplay($Result)

Local $Num="Default Gateway:       192.168.1.1"
Local $Result=StringRegExp($Num,'Default Gateway:\h*[^\r]+',3)
_ArrayDisplay($Result)
Local $Result=StringRegExp($Num,'Default Gateway:\h*([^\r]+)',3)
_ArrayDisplay($Result)
;很神奇的(),加上就只匹配字符串中的IP,不加就匹配整个字符串?   该例非常值得学习与思考[^]与 () 的配合使用!

Local $Num="Sharon Lee Smith, Design Works Incorporated, CA, 95012"
Local $Result=StringRegExp($Num,'([^,]*),([^,]*),([^,]*),(.*)',3)
;Local $Result=StringRegExp($Num,'([^,]*),\w*',3)
;Local $Result=StringRegExp($Num,"(([^,]*),){3}(.*)",3)
_ArrayDisplay($Result)
Local $Num="Alexander Weatherworth, The Crafts Store, CA, 95014"
Local $Result=StringRegExp($Num,'[^,]*',3)
;用*就会匹配出 4个空格字符,因为当*表示0个数量,那[^,]*是匹配0个非,字符,而[^,]又必须匹配一个字符,空格就被匹配出来,依据具体
;环境,也可能匹配出,    或其他什么字符来
;如果将*改成+,那[^,]+是至少匹配一个非,字符,就自然不可能匹配空白字符了,不过[^,]+和([^,]+)这里效果是一样的。
_ArrayDisplay($Result)
;那如果我想匹配出----   Alexander Weatherworth, The Crafts Store
Local $result=StringRegExp($str,"Alexander Weatherworth, [^,]+",3)
;"Alexander Weatherworth,匹配本身, [^,]+至少匹配一个非,字符,到The Crafts Store,中的,时,就自然停止匹配了,想要的匹配结果就得到了
;如果只想匹配出---   The Crafts Store
Local $result=StringRegExp($str,"Alexander Weatherworth, ([^,]+)",3)
;加 () 就OK,()的作用目前还没明白,当个公式记吧。---答:用()会自动捕获他里面表达式匹配的内容,所以匹配的是The Crafts Store
;如果不想匹配他,用Alexander Weatherworth, (?:[^,]+),那将和上面的结果一样。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Local $FilePath="c:\test\test2\test.txt"
Local $Result=StringRegExp($FilePath,"[^\\]+",3)
;感觉就象stringsplit(),但如何用正则提取“文件路径 文件名 文件后缀”?不想用StringRegExpReplace()完成?
_ArrayDisplay($Result)
#cs
总结(感谢afan):
1.以上2例都是通过 [^] 来排除某个符号 .or,最后通过 + 来完成,注意不能用 * 代替+,否则当 *匹配0次时,[^.]会匹配“空格或制表符”
#ce

;example4   零宽断言4种语法的例子
;(?=exp)匹配exp前面的内容(正向预搜索-感谢3mile)
Local $Str="南京银行对同洲电子说:你也算3网融合的巨头,一直在阳痿!" & @CRLF & _
         "同洲电子对南京银行说:你也算银行的佼者,到处叫爹!" & @CRLF & _
                   "nian jing yinhanto tongzhou dian zi said:i am your father. a ha!"
Local $Result=StringRegExp($Str,".*(?=a)",3)
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,".*(?=到处叫爹)",3)
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,"\w+(?=到处叫爹)",3)
;问题:.*就能实现“正向预搜索,\w+就无任何反应?
;理解 :.*将 匹配范围定义到 ”行“,\w+将匹配范围定义到”单词“,不知道这样理解是否正确?但这样理解确实解释的通。比如
;\w+(?=到处叫爹) ,”到处叫爹"根本就不是一个单词,如果把它改成"diedaochujiaodie",那么就会匹配出 'die'   来,真费劲
_ArrayDisplay($Result)
Local$Str="1234567 12345698"
Local$Result=StringRegExp($str,"(?:(?<=\d)\d{3})+\b");如果想从后往前3个数字做处理不如添加 , 可用他
_ArrayDisplay($result,"从给定的字符串后3个数字一组")

#cs上面的正则对这个文本怎么不好使?
===========================================================================
Interface List
0x1 ........................... MS TCP Loopback interface
0x2 ...00 50 56 c0 00 08 ...... VMware Virtual Ethernet Adapter for VMnet8
0x3 ...d8 5d 4c 70 db b3 ...... Realtek RTL8139 Family PCI Fast Ethernet NIC - 数据包计划程序微型端口
===========================================================================
===========================================================================
Active Routes:
Network Destination      Netmask          Gateway       InterfaceMetric
          0.0.0.0          0.0.0.0      192.168.1.1   192.168.1.7          20
      127.0.0.0      255.0.0.0      127.0.0.1       127.0.0.1          1
      192.168.1.0    255.255.255.0      192.168.1.7   192.168.1.7          20
      192.168.1.7255.255.255.255      127.0.0.1       127.0.0.1          20
    192.168.1.255255.255.255.255      192.168.1.7   192.168.1.7          20
    192.168.128.0    255.255.255.0    192.168.128.1   192.168.128.1          20
    192.168.128.1255.255.255.255      127.0.0.1       127.0.0.1          20
192.168.128.255255.255.255.255    192.168.128.1   192.168.128.1          20
      224.0.0.0      240.0.0.0      192.168.1.7   192.168.1.7          20
      224.0.0.0      240.0.0.0    192.168.128.1   192.168.128.1          20
255.255.255.255255.255.255.255      192.168.1.7   192.168.1.7          1
255.255.255.255255.255.255.255    192.168.128.1   192.168.128.1          1
Default Gateway:       192.168.1.1
===========================================================================
Persistent Routes:
None

要求提取出”   Default Gateway: “   后面的   IP地址
#ce
Local   $file=FileOpen(@ScriptDir&"\temp.txt")
Local   $str=FileRead($file)
Local$result=StringRegExp($str,"Default Gateway:\h*([^\r]+)",3)
#cs
\h* 匹配任意数量水平空白字符
[^\r]排除回车符,应该是以 \r 为分割点取后面的部分----我的理解有问题?
[^\r]+匹配若干个不是回车的字符(感谢水木子),这样确实能把后面的内容提取出来,关键在于如何不匹配   Default Gateway: 加上后面的
0或多个空白水平符号,这时的 (),就很关键,加上它就可以不匹配出,但该怎么理解它呢?
水木子老大给的解释:()把希望匹配的内容分组,这样就能匹配出自己的需要了,我觉得()和[^\r]在适用场景理解为分割点,正则表达式模式
匹配的是分割点后面的内容,这样更好理解,呵呵!

补例:
Local $Str="abcdef12345    54321   abcdef"
Local $result=StringRegExp($Str,"\h\d+\h",3);匹配”空白字符及中间的数字“
_ArrayDisplay($result)
Local $result=StringRegExp($Str,"(\h\d+\h)",3)
;匹配”空白字符之间的数字---注意,已经不匹配空白字符“了,这就是()的作用,()把希望 单独匹配 的内容分组
_ArrayDisplay($result)

其实Local$result=StringRegExp($str,"Default Gateway:\h*([^\s]+)",3)更好理解,以 "空白符号为分割点取后面的部分“
Local$result=StringRegExp($str,"Default Gateway:\h*([^\r].*)",3) 将 + 改成.*,也行
#ce
_ArrayDisplay($result)
Local$result=StringRegExp($str,"\s\d+\.\d+\.\d+\.\d+\r",3)
_ArrayDisplay($result)
Local$result=StringRegExp($str,"(?<=\s)\d+\.\d+\.\d+\.\d+(?=\s)",3);扩展一下,提取其中的所有IP形式
_ArrayDisplay($result)
Local$result=StringRegExp($str,"(?<=\s)((\d+\.){3}\d+)(?=\s)",3);为什么不能将上面的正则模式改为这个模式?
_ArrayDisplay($result)

;example5   零宽断言的4种语法练习
Local $Str="南京银行对同洲电子说:你也算3网融合的巨头,一直在阳痿!" & @CRLF & _
         "同洲电子对南京银行说:你也算银行的佼者,到处叫爹!" & @CRLF & _
                        "nian jing yinhanto tongzhou dian zi said:i am your father.a ha!"& @CRLF & _
                        "nian jing yinhangto tongzhou dian zi said:i Am your father.测试空格前后匹配    a   ha!" & @CRLF & _
                        "abc123ABC123zhou dian zi said:i am your father.a ha!"
Local $Result=StringRegExp($Str,"\bam\b",3);匹配单词 am ,OK!
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,"\b(?i)am\b",3);不区分大小写匹配单词 am Am,OK!
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,"\w+(?=a)",3);往前预匹配”单词中有字母a的前面的内容   “,OK!
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,"(?<=a)\w+",3);往后预匹配”单词中有字母a的后面的内容   “,OK!
;问题:只想匹配出ha!后面的 !      该怎么做?
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,"ha([^a].*)",3)
;;利用字符类的排除功能获得了 ”匹配的ha(不包括ha)后面的-行内容“   ,又加深了 [^] 与()的应用,其实可以这样理解,如果 ([^a]),那么
;就是以匹配的内容ha后的 a 为分割点,捕获分割点后面的内容---应该是a后面的----一行内容
;没有()将会匹配以ha (包括ha)开头的之后的行内容
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,"ha[^a].*",3)
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,".*(?=ha)",3)
_ArrayDisplay($Result)
;匹配 ha 之前的行内容
;如果把 .*改成 \w+ 就只能匹配单词中有ha部分的前面的内容了,差距咋这么大呢?一不小心头就大!!!
Local $Result=StringRegExp($Str,".*(?=一直在阳痿)",3)
_ArrayDisplay($Result)
Local $Result=StringRegExp($Str,"(?<=一直在阳痿).*",3)
_ArrayDisplay($Result)
Local $Str="1231123 1244441 abci iabc abciedf"
Local $result=StringRegExp($Str,"(?!i)\w+",3);(?!i)右侧不能出现i
_ArrayDisplay($result)                       
Local $result=StringRegExp($str,"(?!1)\d+",3);(?!1)右侧不能出现1
_ArrayDisplay($result)
Local $result=StringRegExp($Str,"\w+(?<!i)",3);(?!i)左侧侧不能出现i
_ArrayDisplay($result)       
#cs
(?<=<(\w+)>).*(?=<\/\1>)的解释:
匹配不包含属性的简单HTML标签内里的内容
#ce

;examplp6懒惰和贪婪模式,理解并不容易
Local $Str="aabab"
Local $result=StringRegExp($Str,"a.*b",3);贪婪匹配---能匹配时进行最大范围的匹配
_ArrayDisplay($result)
Local $result=StringRegExp($Str,"a.*?b",3);加了?就变成了懒惰匹配
_ArrayDisplay($result)
Local $Str="<div>aaa</div><div>bbb</div>"
Local $result=StringRegExp($Str,"<div>.*</div>",3)
_ArrayDisplay($result)       
Local $result=StringRegExp($Str,"<div>.*?</div>",3)
_ArrayDisplay($result)       
Local $Str="123456789"
Local $result=StringRegExp($Str,"\d{4,5}",3);量词{4,5}执行贪婪匹配,先匹配连续5位数字,没有了连续5位数字匹配,再匹配连续4位数字
_ArrayDisplay($result)       
Local $result=StringRegExp($Str,"\d{4,5}?",3);量词在?作用下变成懒惰匹配,先从指定的最小范围匹配
_ArrayDisplay($result)       

Local $str="dxxxdxxxd"
Local $result=StringRegExp($str,"(d)(\w+)",3)
_ArrayDisplay($result,"第1次匹配结果")
Local $result=StringRegExp($str,"(d)(\w+)(d)",3)
_ArrayDisplay($result,"第1次匹配结果")
Local $result=StringRegExp($str,"(d)(\w+?)(d)",3)
_ArrayDisplay($result,"第1次匹配结果")

;example7对[]加深理解,无论[]里有多少个字符,都只匹配其中的一个字符,没有匹配时,就可以匹配“空格, "等字符
Local $Str="Windows2003"
Local $result=StringRegExp($Str,"",3);匹配结果20 03
_ArrayDisplay($result)
Local $result=StringRegExp($Str,"[^inW]",3);匹配结果 除了inW,字符串中的字符都匹配
_ArrayDisplay($result)
Local $result=StringRegExp($Str,"\w\s\d",3);匹配”任意字符后跟空格再跟0-9中的任意1个数字
_ArrayDisplay($result)

;example8|   分支结构学习,通常用(|)来限定分支匹配范围,如果没有(),那么|作用范围就是 | 两侧整体
Local $Str="cccb"
Local $result=StringRegExp($Str,"^aa|b$",3);匹配结果b
_ArrayDisplay($result)
Local $str = "Mrs Smith"
Local $result = StringRegExp($str, "Mr|Mrs", 3);如果左端的Mr匹配成功,也就意味着“整个正则表达式模式”匹配成功,则|右侧的Mrs将被忽略
_ArrayDisplay($result, '标志=2例子')
Local $result = StringRegExp($str, "Mrs|Mr", 3);如果想即匹配Mrs又匹配Mr,则将最大范围的正则表达式模式放到最左端
_ArrayDisplay($result, '标志=2例子')


;example9捕获组的反向引用的练习
Local $str="abaabbba"
Local $result=StringRegExp($str,"(a|b)\1",3);为什么匹配的不是 aa 而是 ab 呢?
_ArrayDisplay($result);因为_ArrayDisplay($result)返回的是组(a|b)匹配的内容,不是返回“组的反向引用”匹配的内容(感谢3mile)
Local $result=StringRegExpReplace($str,"(a|b)\1","")
MsgBox(0,"应用组的反向引用后再被替换的结果",$result);因为(a|b)\1匹配结果:aabb,被""替换后变成 abba
Local $str = "abaa"
Local $result = StringRegExp($str, "(a|b)\1", 2)
_ArrayDisplay($result, '标志=2例子')

Local $str = "abaabb"
Local $result = StringRegExp($str, "(a|b)\1", 4)
For $i = 0 To UBound($result) - 1
      _ArrayDisplay($result[$i], '标志=4例子')
Next

;example10非捕获组(?:exp)的练习,注意和(exp)及不带括号的exp正则表达式模式的比较
Local $str="010-4394369"
Local $result=StringRegExp($str,"(?:\d{3}-\d{7})",3);捕获的内容保存到最终的正则表达式的匹配结果中
_ArrayDisplay($result)

Local $str = "At this point the remaining pattern matches, so this is the match returned"
Local $result = StringRegExp($str, "(.*)(\w+)$", 3)
;匹配结果是“整个字符串”和“最后一个字母d"
;解释:
; .*作为一个组(.*)会先匹配整个字符串
;然后在一个字符一个字符回退进行匹配,(\w+)匹配至少一个字符,$表示匹配字符串的尾端位置,自然是匹配”d"
_ArrayDisplay($result, '显示匹配结果')

Local $str = "At this point the remaining pattern matches, so this is the match returned"
Local $result = StringRegExp($str, "(.*)\b(\w+)$", 3)
;匹配结果是“整个字符串”和“最后一个单词returned"
;解释:
; .*作为一个组(.*)会先匹配整个字符串
;再一个字符一个字符回退进行匹配,\b由后往前匹配第一个单词的分界处,(\w+)匹配至少一个字符,$表示匹配字符串的尾端位置
_ArrayDisplay($result, '显示匹配结果')
Local $str = "At this point the remaining pattern matches, so this is the match returned"
Local $result = StringRegExp($str, ".*\b(\w+)$", 3)
;匹配结果是最后一个单词returned"
;解释:
; .*会先匹配整个字符串,但此刻他没有被分组 ,所以其匹配的内容没有被捕获
;再一个字符一个字符回退进行匹配,\b由后往前匹配第一个单词的分界处,(\w+)匹配最后一个单词开始的任意数量字符,$表示匹配字符串的尾端位置
_ArrayDisplay($result, '显示匹配结果')
Local $result = StringRegExp($str, ".*\s(.*)", 3); 同样能匹配最后一个单词
_ArrayDisplay($result, '显示匹配结果')

;==========下面这个例子要重点理解
Local $str="At this point the remaining pattern matches, so this is the match returned"
;分析该字符串的结构:"...前略\s\bmatch\b\s\breturned\b$"==-感谢 Pcbar
Local $result=StringRegExp($str,".*\b(.+)$",3)
;注意如果将(.+)更改为(.*),returned就无法被匹配出来,因为*是匹配0个或更多个它前面表达式所匹配的内容,
;所以*可以匹配“空白或字符串尾部的$",他们都是”不可见字符“,所以匹配的结果就是什么都看不到----那前面的“* 可以匹配 $"就是错误的!
;注意 . 是匹配除了 \n 之外的字符,所以它不能匹配诸如\n \f \v\t \s \b ^ $ 这样用来匹配位置的元字符
_ArrayDisplay($result)

;example11
#cs

文本内容如下:
干县令,其于大达亦远矣。”“县”乃古“悬”字,高也;“令”,美也,“干”,追求。是说举着细小的钓竿钓绳,奔走于灌溉用的沟渠之间,只能钓到泥鳅之类的小鱼,而想获得大鱼可就难了。靠修饰琐屑的言论以求高名美誉,那和玄妙的大道相比,可就差得远了。春秋战国时,学派林立,百家争鸣,许多学人策士为说服王侯接受其思想学说,往往设譬取喻,征引史事,巧借神话,多用寓言,以便修饰言说以增强文章效果。庄子认为此皆微不足道,故谓之“小说”,即“琐屑之言,非道术所在”“浅识小道”,也就是琐屑浅薄的言论与小道理之意,正是小说之为小说的本来含义。
希望能匹配出用户名:3-16位(有大小写字母_ -)组成;希望能匹配出密码:6-18位(组成同用户名标准)
user1: 1983_zougk
user2: yanghh-200019
pw1:   a123_vb-new
pw2:   mylo_ve_-1979
temp@sina.comtemp a@sina.comtemp_1980@emai.com.cn temp+1980@emai.com.cn
wu@sohu.com.cn
china_pepwoman@pchina.com.cn
http://www.sohu.com   http://www.sina.com.cnhttp://192.161.1.72
干县令,其于大达亦远矣。

#ce
Local $Str
_Openfile("新建文本文档.txt")
;$Results=StringRegExp($Str,"\b{8,16}\b",3)
$Results = StringRegExp($Str, "\b{8,16}\b", 3)
;_ArrayDisplay($Results,"匹配出用户名")
$Results = StringRegExp($Str, "\s{8,16}\s", 3);又忘了,   \b 是匹配位置; \s 是匹配空白字符,制表符等
;_ArrayDisplay($Results,"匹配出用户名")
;$Results=StringRegExp($Str,"\b(?!+)@(?![\da-z\.-]+)\.(?!{2,6})\b",3)
$Results=StringRegExp($Str,"+://\w+\.\w+(?:[.]\w+)*",3)
_ArrayDisplay($Results,"匹配URL")
$Results=StringRegExp($Str,"\w+([\_\-\+\.]\w+)*@\w+(?:[-.]\w+)* ",3)
_ArrayDisplay($Results,"匹配email")
$Results=StringRegExp($Str,"(?:(?:25|2|??)\.){3}(?:25|2|??)",3)
_ArrayDisplay($Results,"匹配IP")
$Results=StringRegExp($Str,"(?:(?:25|2\d|?\d\d?)\.){3}(?:25|2\d|?\d\d?)",3)
;2\d(?#200-249)|25(?#250-255)|?\d\d?(?#0-199)
_ArrayDisplay($Results,"匹配IP")
;以上匹配IP的正则表达式有个问题,就是如256.193.1.1的非法IP虽然没被匹配,但会截取其中的部分如56.193.1.1被匹配出,所以
;在表达式最前加个\b就OK!---感谢pcbar,一句话惊醒梦中人!

Func _Openfile($txtfile)
        $Open=FileOpen($txtfile)
    If    $Open=-1 Then
          MsgBox(0,"错误提示","文件没有被打开或打开时发生错误")
          Exit
    EndIf
    ;Local $Str=FileRead($Open)       
        $Str=FileRead($Open)        ;滥用 Local 就无法显示,找了半天啊!
        FileClose($Open)
EndFunc

;example12   匹配网页源码的相关内容
#include <array.au3>
;匹配网页源码的相关内容,注意匹配关键词的大小写,当然也可以匹配<div></div>形式内容
$sUrl = 'http://www.sohu.com'
$oHTTP = ObjCreate('microsoft.xmlhttp');通过一个指定的类名microsoft.xmlhttp引用一个COM对象
;$oHTTP = 0 清除被引用的COM对象
$oHTTP.Open('get', $sUrl, False);利用COM对象的get方法获得$sUrl地址的网页源码信息
$oHTTP.Send();发送请求
$sReturnStr = BinaryToString($oHTTP.responseBody, 4);标志 = 4, 二进制 数据原先为 UTF8 编码
;$Result=StringRegExp($sReturnStr,'<SCRIPT.+?</SCRIPT>',3)
$Result=StringRegExp($sReturnStr,'<script.+?</script>',3)
_ArrayDisplay($Result,"测试afan提供的正则显示<SCRIPT>...</SCIRPT>")

$Result=StringRegExp($sReturnStr,'(?ms)\<script\s*src\=.*?\>.*?\<\/script\>',3)
;(?ms) 没弄明白?---(?ms) 多行匹配模式,这样 .也可以匹配 \n了,感谢Sxd
;其实=前不用\也行,不明白3mile为什么用它?
_ArrayDisplay($Result,"测试3mile提供的正则显示<SCRIPT>...</SCIRPT>")

$Result=StringRegExp($sReturnStr,'(<script.*>.*<\/script>?)',3)
;这个正则表达式的懒惰匹配?用不用结果都一样
_ArrayDisplay($Result,"测试xowen提供的正则显示<SCRIPT>...</SCIRPT>")
$Result=StringRegExp($sReturnStr,'<script.*>(?:(?!script)[\s\S])*</script>',3)
;这个正则匹配的内容最全
;首先<script.*>能匹配<script ...>形式的内容
;<script>...</script>之间肯定不能在出现script所以用(?!script)
;[\s\S]匹配空格或非空字符,为了不捕获组里正则表达式匹配的内容用了?:,为了尽可能全的匹配<script>...</script>之间的内容用了*
_ArrayDisplay($Result,"测试xuzhenjun130 提供的正则显示<SCRIPT>...</SCIRPT>")

水木子 发表于 2011-1-7 13:58:09

本帖最后由 水木子 于 2011-1-7 14:08 编辑

坚持你的这份热情,相信你今后定会成为一位了不起的“正则达人”

顺便提点建议,最好是将你这笔记做下分类或编号,比如这段的要点在哪里、自己是否已经完全理解,可以加以注明。
也许我的注意力不够集中,看着看着都不知道自己看到哪里了,或者现在看的这段和上一段是不是同内容,衔接不上。

newuser 发表于 2011-1-7 14:14:52

回复 2# 水木子

谢谢鼓励,现在一直再看资料和请教,很多时候不知道自己是否真的理解了!
另外,自己使用SCITE做笔记,主要是有些代码测试方便,其实自己也曾经想过把笔记作成CHM格式,但自己其实还不会做CHM文件!有机会一定会整理下自己的学习笔记,提供给大家,算是自己的一点贡献吧!

水木子 发表于 2011-1-7 14:20:54

回复 3# newuser

呵呵!看到你学习如此刻苦,真是令我感到惭愧啊!{:face (270):}

newuser 发表于 2011-1-7 15:21:24

回复 4# 水木子
老大,千万别,我的无用功作的太多,一直徘徊不前,老大们闲庭散步,却蒸蒸日上,该脸红的是我!

ashfinal 发表于 2011-2-5 19:19:44

原创必须支持

浪迹红客 发表于 2011-6-6 21:25:39

支持楼主,默默地

itljl 发表于 2011-6-6 21:35:41

多谢分享{:face (356):}

fangbaiyu 发表于 2011-10-24 15:12:05

支持
COPY下来慢慢消化

770317321 发表于 2011-10-27 16:19:59

現在正在看正則呢       感覺有點難度啊呼呼    這個學習下了

user11 发表于 2011-10-27 23:29:27

MARK 慢慢学 这个头大。。

雨林GG 发表于 2011-10-29 04:47:56

肯刻苦学习的人!留着了~ 3Q
页: [1]
查看完整版本: 正则笔记