正则表达式的回溯机制

正则表达式的引擎分析

  • 正则表达式的引擎有两个特点:
    1.默认情况下都是贪婪匹配。
    2.引擎总是着急的,会返回最先匹配到结果

  • 正则引擎的工作原理举例:
    当把cat应用到“He captured a catfish for his cat”,引擎先比较c和“H”,结果失败了。于是引擎再比较c和“e”,也失败了。直到第四个字符,c匹配了“c”。a匹配了第五个字符。到第六个字符t没能匹配“p”,也失败了。引擎再继续从第五个字符重新检查匹配性。直到第十五个字符开始,cat匹配上了“catfish”中的“cat”,正则表达式引擎急切的返回第一个匹配的结果,而不会再继续查找是否有其他更好的匹配。

回溯机制

  • 回溯原理的简单解释
    前面的引擎分析,只是针对简单的正则匹配分析,但是我们都知道正则表达式中还有很多模糊的条件匹配。这时候引擎该如何处理呢?对于计算机而言,处理模糊匹配的最好办法就是穷举,把所有可能的结果都找一遍,别忘了引擎本身都是着急的,也就是说当他匹配到一种可能性之后就不会再匹配剩余的结果。其中这种根据可能性查找的机制就叫回溯。
    举个例子:用正则表达式 <.+>匹配字符串“This is a <EM>first</EM> test”,在这里首先<.+会先匹配出 “<EM>first</EM> test”,但是当>匹配换行符的时候会失败,如果前面你没有用.+这类的模糊语义的话,字符串就会匹配失败,但是由于你用.+这种模糊语义,等于给予了计算机更多的可能性,于是计算机会从最近的可能找起,因此>就会按照可能的顺序去匹配“t”,
    “s”,“e”···一直匹配到">",由于引擎是着急的,所以他马上就返回了匹配结果“<EM>first</EM>”。

  • 分支和回溯
    下面的例子演示了这一过程是如何处理分支的。
    /h(ello|appy) hippo/.test("hellothere, happyhippo");
    此正则表达式匹配“hellohippo”或“happyhippo”。测试一开始,它要查找一个h,目标字符串的第一个字母恰好就是h,它立刻就被找到了。接下来,子表达式(ello|appy)提供了两个处理选项。正则表达式选择最左边的选项(分支选择总是从左到右进行),检查ello是否匹配字符串的下一个字符。确实匹配,然后正则表达式又匹配了后面的空格。然而在这一点上它走进了死胡同,因为hippo 中的h 不能匹配字符串中的下一个字母t。此时正则表达式还不能放弃,因为它还没有尝试过所有的选择,随后它回溯到最后一个检查点(在它匹配了首字母h 之后的那个位置上)并尝试匹配第二个分支选项。但是没有成功,而且也没有更多的选项了,所以正则表达式认为从字符串的第一个字符开始匹配是不能成功的,因此它从第二个字符开始,重新进行查找。它没有找到h,所以就继续向后找,直到第14 个字母才找到,它匹配happy的那个h。然后它再次进入分支过程。这次ello未能匹配,但是回溯之后第二次分支过程中,它匹配了整个字符串“happyhippo”。匹配成功了。

  • 重复与回溯
    下一个例子显示了带重复量词的回溯。

//测试用的字符串
var str = "<p>Para </p>" +
"<img src='smiley.jpg'>" +
"<p>Para </p>" +"<div>Div.</div>";
//正则表达式匹配测试
/<p>.*<\/p>/i.test(str);

正则表达式一上来就匹配了字符串开始的<p>。然后是.*。点号匹配除换行符以外的任意字符,星号这个贪婪量词表示重复零次或多次——匹配尽量多的次数。因为目标字符串中没有换行符,它将吞噬剩下的全部字符串!不过正则表达式模板中还有更多内容需要匹配,所以正则表达式尝试匹配<。它在字符串末尾匹配不成功,所以它每次回溯一个字符,继续尝试匹配<,直到它回到</div>标签的<位置。然后它尝试匹配\/(转义反斜杠),匹配成功,然后是p,匹配不成功。正则表达式继续回溯,重复此过程,直到第二段末尾时它终于匹配了</p>。匹配返回成功,它从第一段头部一直扫描到最后一个的末尾,这可能不是你想要的结果。

  • 注意事项

1.注意减少正则表达式的回溯次数,如果回溯过多,会导致回溯失控出现,即 当一个正则表达式占用浏览器上秒,上分钟或者更长时间。
2.尽可能的使用简单,明确的语义去编写,正则表达式。
3.其他优化事项见正则表达式优化诀窍

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348

推荐阅读更多精彩内容

  • 初衷:看了很多视频、文章,最后却通通忘记了,别人的知识依旧是别人的,自己却什么都没获得。此系列文章旨在加深自己的印...
    DCbryant阅读 3,993评论 0 20
  • 正则表达式到底是什么东西?字符是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等...
    狮子挽歌阅读 2,141评论 0 9
  • `>本文是 Jan Goyvaerts 为 RegexBuddy 写的教程的译文,版权归原作者所有 在本文中讲述了...
    极客圈阅读 2,071评论 0 5
  • 本文译自 制作正则引擎的作者 Jan Goyvaerts 为工具 RegexBuddy 写的教程版权归原作者所有注...
    极客圈阅读 3,277评论 0 25
  • 注:本篇文章只为方便查看,特此保留,如有冒犯,敬请谅解!!! 本文目标 30分钟内让你明白正则表达式是什么,并对它...
    阿杰Alex阅读 1,479评论 0 10