00-1010,当音符随机组合在一起,可能是噪音。当同样的音符通过作曲家的手,你可以创作出非常优美的音乐。表演者也可以根据乐谱演奏优美的音乐,但他/她可能不知道如何改变音符的组合来使音乐更加优美。作为一个普通用户,如果不知道正则引擎的原理,也可以写一个符合自己需求的正则,但是如果不知道原理,很难写出一个高效无隐患的正则。所以对于经常使用正则或者对深入研究正则感兴趣的人来说,了解正则引擎的匹配原理是很有必要的。00-1010常规发动机可以分为两个不同的类别:DFA和NFA,而NFA基本上可以分为传统的NFA和POSIX NFA。一个DFA确定性有限自动机确定性有限自动机NFA非确定性有限自动机确定性有限自动机传统的NFAPOSIX NFADFA引擎匹配速度快,因为它不需要回溯,但是不支持捕获组。因此,不支持反向引用和$number。目前使用DFA引擎的语言和工具主要有awk、egrep和lex。POSIX NFA主要指符合POSIX标准的NFA发动机。它的主要特点是提供最长最左匹配,即在找到最左最长匹配之前会继续回溯。像DFA一样,非贪婪模式或者忽略优先级量词对POSIX NFA也是没有意义的。大多数语言和工具使用传统的NFA引擎,该引擎有一些DFA不支持的特性:捕获组、反向引用和$number引用;环顾四周。=…)、(?…)、(?=…)、(?)),或者有些文章叫预搜;忽略优化的量词(?*?{m,n}?{m、}?),或者有些文章叫非贪婪模式;优先量词(?*、{m,n}、{m,},目前只支持Java和PCRE),以及固化分组(?…)。发动机的区别不是本文的重点,仅做简单介绍,感兴趣的可以参考相关文献。
对于字符串“abc”,它包括三个字符和四个位置。
来源:abc正则表达式:abc匹配过程:首先字符“A”获得控制权,匹配从位置0开始,“A”匹配“A”。匹配成功后,控制权交给字符“B”;由于“A”已被“A”匹配,“B”尝试从位置1匹配,“B”匹配“B”。匹配成功后,控制权交给“C”。用“c”匹配“c”,匹配成功。此时,正则表达式匹配完成,并报告匹配成功。匹配结果为“abc”,起始位置为0,结束位置为3。
来源:ab正则表达式:ab?量词“?”属于匹配优先量词。当它可以匹配或不匹配时,它会选择先尝试匹配。只有当这种选择使得整个表情无法成功匹配时,才会尝试放弃匹配的内容。量词“?”这里。它用来修饰字符“b”,那么“b?”是一个整体。匹配过程:首先字符“a”获得控制权,匹配从位置0开始,“a”匹配“a”。匹配成功后,控制权交给角色“b?”。因为“?”是一个匹配的优先量词,所以我们会先尝试匹配它,也就是“b?”匹配“B”,匹配成功,控制权交给“C”,同时记录一个备选状态;用“c”匹配“c”,匹配成功。该记录的替代状态被丢弃。此时,正则表达式匹配完成,并报告匹配成功。匹配结果为“abc”,起始位置为0,结束位置为3。
来源:ac正则表达式:ab?c匹配过程:首先字符“a”获得控制权,从位置0开始匹配,“a”匹配“a”。匹配成功后,控制权交给角色“b?”。先试着匹配,通过“b?”匹配“C”,同时记录一个备选状态。如果匹配失败,回去找备选状态,“B?”。无视匹配,放弃控制权,交给“C”;用“c”匹配“c”,匹配成功。此时,正则表达式匹配完成,并报告匹配成功。匹配结果为“ac”,起始位置为0,结束位置为2。其中的" b "什么都不匹配。
来源:abd正则表达式:ab?c匹配过程:首先字符“a”获得控制权,从位置0开始匹配,“a”匹配“a”。匹配成功后,控制权交给角色“b?”。先试着匹配,通过“b?”匹配“B”,并记录备选状态,匹配成功,控制权交给“C”;用“c”匹配“d”,匹配失败。这时,回去找记录的替代状态,“b?”。忽略匹配,即“b?”如果与“B”不匹配,放弃控制权,交给“C”;用“c”匹配“b”失败。此时,第一次匹配尝试失败。正则化引擎向前驱动正则化,并尝试从位置1开始匹配,“A”匹配“B”。匹配失败,没有替代状态,第二轮匹配尝试失败。继续向前行驶,直到匹配尝试在位置3失败,匹配结束。此时会报告整个表达式匹配失败。
来源:ab正则表达式:ab?c量词"?"忽略优先量词。如果可以匹配或者不匹配,会先选择不匹配。只有当这个选择会让整个表达式匹配不成功时,才会尝试匹配。这里的量词"?"是用来修饰字符“b”的,那么“b?"是一个整体。匹配过程:首先字符“a”获得控制权,匹配从位置0开始,“a”匹配“a”。匹配成功,控制权交给角色“b?";先试着忽略匹配,也就是“b?"不匹配,同时记录一个备选状态,给“C”控制;用“c”匹配“b”,匹配失败。这时,回去找记录的替代状态,“b?"尽量匹配,也就是“b?"要匹配“B”,匹配成功,控制权交给“C”;用“c”匹配“c”,匹配成功。此时,正则表达式匹配完成,并报告匹配成功。匹配结果为“abc”,起始位置为0,结束位置为3。在哪个“b?"匹配字符“b”。
源字符串:a12正则表达式:(?=[a-z])[a-z0-9] $元字符" "和" $ "仅匹配位置,并四处查看”(?=[a-z])"只匹配,不占用字符,不保存匹配内容到最终匹配结果,所以都是零宽度。这种规律性的含义是字母和数字匹配,第一个字符是一串字母。匹配过程:首先,元字符“”获得控制权,匹配从位置0开始,其中“”匹配起始位置“位置0”。匹配成功后,控制权交给顺序环视”(?=[a-z])”;"(?=[a-z])”要求其位置右侧必须是字母才能匹配成功,零宽度子表达式不互斥,即同一个位置可以被多个零宽度子表达式匹配,因此也尝试从位置0开始匹配,位置0右侧是字符“a”,符合要求,匹配成功,控制权赋予“[a-z0-9]”;因为”(?=[a-z])“仅匹配,不将匹配的内容保存到最终结果,以及”(?=[a-z])”位于位置0,因此“[a-z0-9]”也尝试从位置0开始匹配。“[a-z0-9]”先尝试匹配“a”,再尝试匹配成功,可以成功匹配下一个“1”和“2”。字符“$”尝试从位置3开始匹配,它匹配结束位置,即“位置3”,匹配成功。此时,正则表达式匹配完成,并报告匹配成功。匹配结果为“a12”,起始位置为0,结束位置为3。其中“”与位置0匹配。=[a-z])“匹配位置0,“[a-z0-9]”匹配字符串“a12”,而“$”匹配位置3。