正则表达式

元字符:有特殊含义的字符
排除型字符组:[^str],在当前位置匹配一个没有列出的字符(必须匹配一个字符),如果理解为不要匹配列出的字符就暗示不出现任何字符也可以
字符组简记:\d,\s,\w,\D,\S,\W,[0-9a-zA-Z],Perl正则流派
POSIX方括号表达式:对[0-9a-zA-Z]仍支持,但\在[]不表示转义([\d]只能匹配\和d不能匹配[0-9])
POSIX字符组:[:alnum:],[:alpha:],[:ASCII:],[:blank:],[:cntrl:],[:digit:],[:graph:],[:lower:],[:print:],[:punct:],[:space:],[:upper:],[:word:],[:xdigit:]
点号.:匹配当前语言环境下的除换行符外的任意单个字符(ASCII-1B,GBK-2B,UTF8-3B)
匹配任意字符:[\d\D],[\s\S],[\w\W]
匹配优先量词:?,*,+,{n},{m,n},{m,}
忽略优先量词:??,*?,+?
占有优先量词:?+,*+.++
转义:\.,\?,\*,\+,\??,\*?,\+?,()要求为\(\),{}和[]只转义开括号即可\{},\[]
括号:1多选结构(...|...|...),2子表达式爱量词作用()?*+,3反向引用捕获分组\num(反向引用的是前面分组匹配成功的结果而非引用的rex,按左括号由左至右顺序给分组编号)
命名分组:(?<name>rex),匹配rex并捕获到名字为name的分组中,用于代替多层括号嵌套时默认分组\num不易辨别的情况
非捕获分组:(?:rex)只限定量词的作用范围,但不捕获
断言:指明字符串左(右)满足某种规则,只匹配位置.有1单词边界\b\B,2行起始^和结束$,3环视
环视:当前位置向右判断是顺序,向左判断是逆序;子表达式匹配的字符串必须出现为肯定,不能出现为否定.肯定顺序(?=rex),否定顺序(?!rex),肯定逆序(?<=rex),否定逆序(?<!rex)
匹配模式:匹配时使用的规则,(?i)不区分大小写,(?s)单行模式,(?m)多行模式,(?#comment)注释为comment
单行模式和多行模式没有任何关系,单行模式影响点号的匹配在单行模式下点号可匹配换行在内的任何字符(默认不匹配换行符);多行模式影响^和$匹配,多行模式^和$可匹配字符串内某一行的起始和结束位置(默认匹配整个字符串的起始和结束位置)
模式修饰符(?modifier):从现在开始使用某个模式,若在rex起始位置则作用于整个rex,若在rex内则作用于其后的表达式eg:th(?:i)e~the或thE,若在()内则作用于该()
失效修饰符(?:-modifier):模式生效到此为止.eg:(?i)(a|b)(?-i)C~AC,aC,Bc,bc
正则文字:在源码中看到的rex,是rex的表现形式.eg:\d的正则文字是\和d,匹配[0-9],在生成rex时进行"正则转义"才能将正则文字中的\d识别为[0-9]
字符串\\\\经过"字符转义"变为正则文字\\再经过"正则转义"变为\,才能匹配反斜线;\\n字符串转义为正则文字\n再正则转义为NL才能匹配换行
优先级:子表达式(subrex)>量词?*+>拼接abc>多选a|bc
多选不一定必须使用(),但是使用()明确多选的范围且可使用反向引用(不过在rex复杂时分组会严重影响效率),建议不需要反向引用时使用非捕获型括号(?:)来配合多选
\w:ASCII[0-9a-zA-Z]:Unicode[\p{L1}\p{Lu}\p{Lt}\p{Lo}\p{Lm}\p{Nd}\d{Pc}]
\d:ASCII[0-9]:Unicode[\p{Nd}]
\s:ASCII[\f\n\r\t\v\x20]:Unicode[\f\n\r\t\v\x85\p{Z}]

正则表达式rex匹配的两条通用规则:
1.优先选择最左端的匹配结果.eg: fat|cat|belly|your ~ The dragging belly1 indicat2es that your3 cat4 is too fat5.(数字表示被匹配的顺序)
2.标准量词是匹配优先的*,?,+,{m,n},匹配优先即问题匹配多于匹配成功下限的字符,尽可能多的匹配,直至匹配上限为止.
讨论DFA和NFA在多选或者有量词作用时可清楚地辨别异同:
DFA:awk,egrep,mysql
NFA:sed,grep,less,more,Python,Java,Ruby,PHP,.NET,GNU Emacs
DFA:文本主导,引擎由左至右扫描字符串,同时去筛选rex,每扫描一个字符就在rex中筛选匹配字符串的rex,故rex若匹配肯定是最长匹配.每个字符只会被扫描匹配一次,速度快.
NFA:表达式主导,按表达式逐个去匹配字符,字符可能被不同的表达式匹配,也被同一表达式反复匹配.尝试所有rex依然不能匹配才会报告失败.速度慢,回溯是重要功能,支持捕获型括号、反向引用、环视、占有优先量词和固化分组.
回溯:1.在"进行尝试"和"跳过尝试"间选择,匹配优先量词?,*,+,{m,n}会优先进行尝试,忽略优先量词会优先跳过尝试;2.距离当前最近储存的选项就是当匹配失败强制回溯时的返回点,即LIFO后进先出.(我的理解:在rex为多选结构或有量词作用时才有备选状态,才会有回溯的概念)
匹配优先和忽略优先是为整个rex匹配服务的,若匹配失败,二者已经尝试了所有可能.
固化分组(?>rex):固化分组括起来的相当于一个整体,不会在固化分组内有多个备用状态,可加快报告匹配失败的速度,在固化分组内有量词或多选结构时,量词依然有效.
结论:1.只匹配期望的文本,排除不期望2.易于控制和理解3.若用NFA则优化rex保证效率(1.提高效率尽量避免回溯2..多选结构分支越多效率越低3.限制匹配优先量词作用范围,最好能够对量词作用表达式的前后利用环视或^$\b\B定界不然反复回溯影响效率4.慎用.*来匹配)
eg:DFA和NFA匹配原理,rex:to(nite|knight|night) 字符串:after tonight
NFA:
1.引擎扫描rex第一个字符为t,去匹配字符串最左侧字符a,结果不匹配,字符串向右移一位再来匹配
2.rex的t不匹配字符串的f,字符串向右移一位再来匹配
3.rex的t匹配字符串的t并保存为备用状态,引擎扫描rex的第二个字符为o,去匹配字符串t后的字符e,结果不匹配,回溯至备用状态
4.rex的t不匹配字符串的e,字符串向右移一位再来匹配,rex的t不匹配字符串的r,字符串向右移一位再来匹配,rex的t不匹配字符串的空格,字符串向右移一位再来匹配
5.rex的t匹配字符串的t并保存为备用状态1,引擎扫描rex的第二个字符为o匹配字符串t后的字符o保存为备用状态2
6.引擎扫描第一个多选分支的第一个rex字符为n匹配字符串n,并保存为备用状态3(?不确定是否保存为备用状态3),引擎扫描第一分支的第二个rex字符为i匹配字符串i并保存为备用状态4(?不确定是否保存为备用状态4),引擎扫描第一分支的第三个rex字符为t不匹配字符串g,回溯至备用状态2(因为每个分支是并列的,所以尝试第二个分支进行匹配时回溯至第一个分支未匹配的状态,即备用状态2)
7.引擎扫描第二个多选分支的第一个rex字符为k不匹配字符串n
8.引擎扫描第三个多选分支的第一个rex字符为n匹配字符串n并保存为备用状态5,引擎扫描第三个多选分支的第二个rex字符为i匹配字符串i并保存为备用状态6,引擎扫描第三个多选分支的第三个rex字符为g匹配字符串g并保存为备用状态7,引擎扫描第三个多选分支的第四个rex字符为h匹配字符串h并保存为备用状态8,引擎扫描第三个多选分支的第五个rex字符为t匹配字符串t,报告匹配成功
DFA:
1.引擎扫描字符串第一个字符为a不匹配rex的第一个字符t
2.引擎向右扫描字符串第二个字符为f不匹配rex的第一个字符t
3.引擎向右扫描字符串第三个字符为t匹配rex的第一个字符t,可匹配的rex为to(nite|knight|night),字符串下一个字符为e不匹配rex的第二个字符o
4.引擎向右扫描字符串第四个字符为e不匹配rex的第一个字符t,引擎向右扫描字符串第五个字符为r不匹配rex的第一个字符t,引擎向右扫描字符串第六个字符为空格不匹配rex的第一个字符t
5.引擎向右扫描字符串第七个字符为t匹配rex的第一个字符t,可匹配的rex为to(nite|knight|night);字符串下一个字符o,可匹配的rex为to(nite|knight|night);字符串下一个字符n,可匹配的rex为to(nite|night);字符串下一个字符i,可匹配的rex为to(nite|night);字符串下一个字符g,可匹配的rex为tonight;字符串下一个字符h,可匹配的rex为tonight;字符串下一个字符t,可匹配的rex为tonight.匹配成功.


Python:
r'str':原生的str,不必转义.在使用rex时,r'str'可直接表示为正则文字.
(?P<name>rex)命名分组,group(name)获得分组匹配的文本
匹配模式:不区分大小写re.I和re.IGNORECASE,单行re.S和re.DOTALL,多行re.M和re.MULTILINE,注释re.X和re.VERBOSE
(?modifier)无论出现在什么位置都对整个rex生效
python不支持失效修饰符(?-modifier)
python2字符串默认采用ASCII编码,多字节被拆为多个单字节,故.不能匹配单个汉字,若将整个字符串指定为Unicode则可以匹配
python2默认ASCII匹配规则,python3默认Unicode匹配规则
[\u4e00-\u9fff]匹配中文
python支持如下:
字符组[...]和[^...]支持Unicode
POSIX字符组[:digit:]只匹配ASCII字符
字符组简记\d\D\s\S\w\W
行起始^和结束$(\Z)
单词边界\b\B
顺序环视(?=rex),(?!rex)
匹配模式i,s,m,x,a,u
模式作用范围(?modifier)
分组捕获和引用(...),\num,$num
命名分组(?P<name>rex),(?P=name)
非捕获分组(?:rex)
多选(...|...)
匹配和忽略优先量词?,*,+,??,*?,+?
re.compile(rex[,flags])显式编译正则表达式对象
re.search(rex,str[,flags])测试rex能否在str中找到匹配若匹配返回MathObject否则返回None,flag表示匹配模式
re.match(rex,str[,flags])只会在字符串开始位置尝试匹配,re.search则无此限制,其他相同.re.match(r'\d','a1') != None#False,re.search(r'\d','a1') != None#True
re.findall(rex,str[,flags])一次找出rex在str中的所有匹配,返回list.若rex中存在捕获分组,则返回list的元素并非整个表达式匹配的文本而是各个分组所匹配文本构成的tuple
re.finditer(rex,str[,flags])返回一个迭代器,可从左到右逐个遍历每次匹配的MathObject对象依次进行处理
re.split(rex,str[,maxsplit=0,flags])用rex能够匹配的文本切分str,maxsplit表示切分次数
re.sub(rex,replacement,str[,count,flags])将str中rex能够匹配的字符串替换为replacement

posted on 2018-07-10 23:29  AiYS  阅读(137)  评论(0编辑  收藏  举报

导航