- #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)
复制代码
|