1.正在表达式引擎分类:DFA,NFA;由于众多变体不能统一,所以用POSIX标准来规范(POSIX规定什么样的表达式应该匹配什么样的字符串),其中DFA基本满足,但NFA需要满足则需要很多改变,就出现了传统NFA(不符合POSIX标准)和POSIX NFA(满足POSIX标准)。所以可以分为3类 , DFA,传统NFA和POSIX NFA。
2.确定是否为传统NFA。 传统NFA支持“忽略优先量词”,而其他两种则不支持。
测试表达式“nfa|nfa.not" 来匹配串”nfa.not“ ,如果只有nfa匹配则为传统NFA
3.区分DFA与POSIX NFA
DFA不支持捕获型括号和回溯。
测试方法
例如:
echo "_XX=================================================="|egrep 'X(.+)+X'
如果执行很久甚至报栈溢出,则该egrep 使用的不是DFA引擎
注意:某些工具使用多种引擎,会根据表达式进行引擎选择
4.
6. \b\w+s\b 匹配regexs,其中\w+匹配了regex部分,按规则\w+可以匹配整个单词,但是为了让s匹配,“+”这种匹配优先量词被迫少匹配一次,"尽可能的完成匹配"正式匹配优先量词的另一层含义
表达式主导引擎:通过表达式来淘汰当前匹配位置
文本主导引擎(DFA引擎):通过当前文本来淘汰表达式
6.先来先服务
多个匹配优先量词,会让顺序上优先的量词尽可能的先匹配
7.NFA引擎是表达式主导(表达式中的控制权在不同的元素之间转换)的。
8.回溯:表达式优先的引擎,在量词和多选分支中,当前匹配失败返回尝试下一分支的情形。
9.回溯机制中的两个问题
哪个分支应当首先选择?:对应匹配优先量词,引擎会优先选择”进行尝试“,而对于忽略优先量词,则会选择跳过尝试。
回溯时选择哪个保存的状态?:(图的深度遍历),距离当前最近储存的选项。
10.关于匹配优先,忽略优先和否定环视
eg <b>asdfsadfdsafdsaf<\b> adsfdsajlf <b>adsfsadfsadfdsa<\b>
用匹配优先量词 表达式"<b>.*<\\b>将匹配 <b>asdfsadfdsafdsaf<\b> adsfdsajlf <b>adsfsadfsadfdsa<\b>
用忽略优先量词 表达式"<b>.\{-}<\\b>将匹配 <b>asdfsadfdsafdsaf<\b> adsfdsajlf <b>adsfsadfsadfdsa<\b>
用否定顺序环视 表达式"<b>\(\(<\\b>\)\@!.\)*<\\b>将匹配 <b>asdfsadfdsafdsaf<\b> adsfdsajlf <b>adsfsadfsadfdsa<\b>
用否定顺序环视 表达式"<b>\(\(<\\b>\)\@!.\)*<\\b>将匹配 <b>asdfsadfdsafdsaf<\b> adsfdsajlf <b>adsfsadfsadfdsa<\b>
11.匹配优先和忽略优先都是为全局匹配服务,如果报告全局匹配失败就会尝试未走过的分支,如果已经匹配成功则不尝试未走过的分支。 匹配优先和忽略优先主要区别就是匹配尝试分支的秩序相反,这就是用作性能考量的尺子
12.固化分组(?>...),不同于匹配优先和忽略优先,他会在匹配成功的情况下舍弃固话分组匹配过程中的备用状态,导致这些备用状态不能回溯,而匹配优先和忽略优先在匹配失败的情况下尝试的分支是一样的。 固话分组舍弃的状态只是固话分组匹配过程中产生的状态,对应分组之前和之后的状态没有影响,如果发生回溯这些状态时可以用的。
以vim为例,表达式"\.\d\d\([1-9]?\)\@>\d\+" 能匹配”0.625000“但不能匹配”0.625“,意外匹配0.625时,固话分组匹配成功后舍弃了”?“不匹配的状态所以在后面\d\+匹配失败时无法回溯。
13.占有优先量词(++)与固化分组不同的是,占有优先量词从不交还匹配的字符,就是说根本不产生备用状态。
14.环视结构将放弃所有备用状态。可以用环视结构模拟固化分组和占有优先量词,
15.传统NFA多选结构是在多个表达式中按从左到右顺序进行匹配,能够匹配成功则不继续尝试右边的表达式,而DFA和POSIX NFA是匹配优先的,选择匹配最长的结果。
16.DFA在有多个匹配结果的情况下回选择最长的