找回密码
 加入
搜索
查看: 5216|回复: 7

[原创] 学习deercao的正则笔记

  [复制链接]
发表于 2010-12-21 10:38:05 | 显示全部楼层 |阅读模式
赚个原创吧,毕竟自己也学习了,呵呵!
#cs
学习deercao提供的正则30分钟资料的笔记

正则表达式就是个字符串处理语言,是用来“查找你想要的字符串和进行字符串的替换“。
网页、程序或文件中有关文本内容的处理部分都可以应用正则表达式完成。

在正则表达式中,元字符有特殊功能,如\w匹配“数字、字母、下划线、汉字”,这个在afan的正则表达式工具中有详细说明。

字符类:用[]括起来的就是一个字符类,如[aeu]匹配 a 或 e 或 u   , [.?!] 匹配 .   或   ?  或  ! ,此刻的字符类里的元字符就
        不代表特殊的含义了。
                ([^\r]+) 我以前理解为”排除回车符号的至少一个什么字符的匹配“不如”匹配一个及以上非回车的字符“好理解,而且要注意其中
                ()的适用场景,用不用他效果有时差别真的很大!

|  :就是多条件匹配,如用 \d{3}-\d{7}|\d{7} 匹配010-1234556或1234556,但注意别写成 \d{7}|\d{3}-\d{7},因为它只能匹配连续的
    7位数字或3位数字-7位数字中的前7位了,我的理解是“在进行多条件匹配时,要把最大的匹配范围写到最前面,然后依次减小匹配范围”
        
分组 :用  () 括起来就是一个分组,如用于IP地址的匹配模式  (\d{1,3}\.){3}\d{1,3},分组()里的内容意思是”匹配1-3位的数字后面跟个
       .  的形式重复3次,最后再跟1个1-3位的数字。
           分组还可以后向引用 ,如IP可用模式 (\d{1,3}\.){3}\d{1,3}\.匹配,就可以写成 (\d{1,3}\.){3}\1,这个\1就代表分组1(\d{3}\.)
           所匹配的文本内容了。分组号是从 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种语法:
    (exp)   匹配exp,并捕获文本到自动命名的组里
        (?<GroupName>exp)  匹配exp,并捕获文本到 自定义的<GroupName>组里
        (?:exp)  匹配exp,但不给组分配组号,也不捕获文本到组里
        
零宽断言语法(下面有例子) :
    (?=exp)   匹配exp前面的内容
        (?<=exp)  匹配exp后面的内容
        (?!exp)   可以看成 Str(?!exp),就是Str后不匹配exp
        (?<!exp)  可以看成(?<!exp)Str,就是Str前不匹配exp
        
注释:语法为 (?#comments)
    例 2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)。

懒惰匹配和贪婪匹配        例  用 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次以上,但尽可能少重复 

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

曾经犯过的错误:
1。

#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]匹配X ,想多了!
_ArrayDisplay($Result) ;OK
Local $Result=StringRegExp($Str,"\b[1-9]\d{5}\b",3)
;Local $Result=StringRegExp($Str,"[^\d][1-9]\d{5}$");条条大路通罗马,感谢lpxx
;Local $Result=StringRegExp($Str,"[1-9]\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,()的作用目前还没明白,当个公式记吧。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

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 yinhan  to tong  zhou 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)

#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       Interface  Metric
          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.7  255.255.255.255        127.0.0.1       127.0.0.1          20
    192.168.1.255  255.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.1  255.255.255.255        127.0.0.1       127.0.0.1          20
  192.168.128.255  255.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.255  255.255.255.255      192.168.1.7     192.168.1.7          1
  255.255.255.255  255.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)
;\h* 匹配任意数量水平空白字符
;[^\r]排除回车符,应该是以 \r 为分割点取后面的部分----我的理解有问题?
;[^\r]+  匹配若干个不是回车的字符(感谢水木子),这样确实能把后面的内容提取出来,关键在于如何不匹配   Default Gateway: 加上后面的
;0或多个空白水平符号,这时的 ()  ,就很关键,加上它就可以不匹配出,但该怎么理解它呢?
;其实  Local  $result=StringRegExp($str,"Default Gateway:\h*([^\s]+)",3)  更好理解,以 "空白符号为分割点取后面的部分“
;Local  $result=StringRegExp($str,"Default Gateway:\h*([^\r].*)",3) 将 + 改成  .*  ,也行
_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   学习利用[^] 或 ([^])与零宽断言的后匹配的比较
Local $Str="南京银行对同洲电子说:你也算3网融合的巨头,一直在阳痿!" & @CRLF & _
           "同洲电子对南京银行说:你也算银行的佼者,到处叫爹!" & @CRLF & _
                        "nian jing yinhan  to tong  zhou dian zi said:i am your father.a ha!"  & @CRLF & _
                        "nian jing yinhang  to tong  zhou dian zi said:i Am your father.测试空格前后匹配    a     ha!" & @CRLF & _
                        "abc123  ABC123  zhou 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 $result=StringRegExp($Str,"ni(?!i)",3)
_ArrayDisplay($result)
Local $result=StringRegExp($Str,"(?<![a-z])\d{3}",3);匹配不是以26个小写字母开头的3位数字
_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);匹配不是以26个小写字母开头的3位数字
_ArrayDisplay($result)
 楼主| 发表于 2010-12-21 10:38:51 | 显示全部楼层
回复 1# newuser
自己顶一下!
发表于 2010-12-21 11:09:59 | 显示全部楼层
我也帮你顶。
 楼主| 发表于 2010-12-21 11:11:42 | 显示全部楼层
回复 3# lpxx
自己的刚刚学习笔记,希望大家给予鼓励,非常感谢!
发表于 2010-12-21 11:30:29 | 显示全部楼层
本帖最后由 水木子 于 2010-12-21 11:32 编辑

非常不错!记录下自己的学习过程,不过我看了你的笔记,貌似好几处你的理解都还存在问题,不过不要急咱们慢慢学习。

至于你这贴该不该归纳在这个版块还有待思考。
 楼主| 发表于 2010-12-21 13:39:40 | 显示全部楼层
回复 5# 水木子
谢谢,能将我笔记中的错误指点给我吗?我之所以贴出来,一是鼓励自己,而是希望有人能指出我的理解错误,这样我可以更有信心的学下去,这个才是我的目的.
发表于 2010-12-21 14:07:06 | 显示全部楼层
顶你一个。。
发表于 2011-1-27 23:28:11 | 显示全部楼层
已收藏。。。。。。。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-5-2 19:10 , Processed in 0.074060 second(s), 19 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表