正则进阶之,回溯, (贪婪* 非贪婪+? 独占++)三种匹配量词

正则的回溯

  在正则表达式实现中,回溯是匹配过程的基本组成部分,它是正则表达式如此好用和强大的根源。然而,回溯计算代价很高,如果设计失误,将导致失控。回溯是影响整体性能的唯一因素,理解它的工作原理,以及如何减小使用频率,可能是编写高效正则表达式的关键点。

  当一个正则表达式扫描目标字符串时,从左到右逐个扫描正则表达式的组成部分,在每个位置上测试能不能找到一个匹配。对于每一个量词和分支,都必须确定如何继续进行。如果是量词(如*+?或者{2,}),那么正则表达式必须确定何时尝试匹配更多的字符;如果遇到分支(通过|操作符),那么正则表达式必须从这些选项中选择一个进行尝试。

  当正则表达式做出这样的决定时,如果有必要,它会记住另一个选项,以备返回后使用。如果所选方案匹配成功,正则表达式将继续扫描正则表达式模板,如果其余部分匹配也成功了,那么匹配就结束了。

  但是,如果所选择的方案未能发现相应匹配,或者后来的匹配也失败了,正则表达式将回溯到最后一个决策点,然后在剩余的选项中选择一个。继续这样,直到找到一个匹配,或者量词和分支选项的所有可能的排列组合都尝试失败后放弃这一过程,然后移动到此过程开始位置的下一个字符上,重复此过程。

例如:abc123d

当正则引擎用正则w*(d+)去匹配字符串abc123d时,会先用w*去匹配字符串abc123d,
  首先,w*会匹配字符串abc123d的所有字符,
  然后再交给d+去匹配剩下的字符串,而剩下的没了,这时,w*规则会吐出一个字符,给d+去匹配,同时,在吐出字符之前,记录一个点,这个点,就是用于回溯的点;
  然后d+去匹配n,发现并不能匹配成功,w*再吐出一个字符,w*会先再次记录一个回溯的点,再吐出一个字符。
  这时,w* 匹配的结果只有abc12了,已经吐出3d了,d+再去匹配3,发现匹配成功,则会通知引擎,匹配成功了,就直接显示出来了。
所以,(d+)的结果是3,而不是123。

正则表达式中匹配的三种量词:贪婪(Greedy)、勉强(Reluctant)、独占(Possessive)

贪婪      非贪婪(?)      独占(+)
X?        X??         X?+
X*        X*?         X*+
X+       X+?           X++
X{n}       X{n}?           X{n}+
X{n,}         X{n,}?         X{n,}+
X{n,m}     X{n,m}?      X{n,m}+

Greedy:贪婪
  匹配最长。在贪婪量词模式下,正则表达式会尽可能长地去匹配符合规则的字符串,且会回溯。

Reluctant :非贪婪
  匹配最短。在勉强量词模式下,正则表达式会匹配尽可能短的字符串。

Possessive :独占
  同贪婪一样匹配最长。不过在独占量词模式下,正则表达式尽可能长地去匹配字符串,一旦匹配不成功就会结束匹配而不会回溯。

时间: 2024-10-12 09:00:16

正则进阶之,回溯, (贪婪* 非贪婪+? 独占++)三种匹配量词的相关文章

正则表达式中的贪婪非贪婪

近几天在做几个爬虫,分析网页url的时候,抓取总是出现问题.后来了解到是贪婪和非贪婪模式的问题. 记录一下本是想在一个html中抓取大量这种模式的href连接 <a href="http://www.xxxx.info/post/90934717083">xxxxx</a></br> 写的正则表达式为 reg = r'<a href="(.+)">' 经过Regulator分析后,下面语句也匹配了出来 href=&qu

正则贪婪,非贪婪,分组,前瞻

1.贪婪模式 正则是:/\d{3,5}/g,字符串是 12345678 那么exec 方法或者match方法返回的结果是什么呢? 是 [123,456] 还是 [1234,5678] 还是[12345] 答案是:[12345] . 正则表达式默认是贪婪模式,即尽可能多的匹配,如果失败那么减一匹配直到最小值.在这种情况下前面5个数字匹配后,下标来到6处,678不会再匹配 2.非贪婪模式 让正则表达式尽可能少的匹配,也就是说一旦成功匹配就不在继续尝试就是非贪婪模式 只要在量词后加上?即可 '1234

python 贪婪 非贪婪 匹配

python re模块还是需要重新学习. python readline 和 readlines(), readline() , read() 三者之间的区别,以前一直都不清楚,现在搞清楚是怎么回事了. readlines() 可以一起显示出整个文件,这个也是迭代显示的,需要追行显示,迭代器的指针会被消耗的. python 中的正则是匹配换行以外的所有的字符..* 是匹配不了所有的字符的.在某些情况下,我的结论是正确的,但是在某些情况下,我的结论又是错误的.刚才遇到的问题,现在终于知道是怎么回事

Java 正则表达式 量词 --- 三种匹配模式【贪婪型、勉强型、占有型】

1.Greediness(贪婪型):最大匹配X?.X*.X+.X{n,}都是最大匹配.例如你要用“<.+>”去匹配“a<tr>aava</tr>abb”,也许你所期待的结果是想匹配“<tr>”,但是实际结果却会匹配到“<tr>aava</tr>”.这是为什么呢?下面我们跟踪下最大匹配的匹配过程.①“<”匹配字符串的“<”.②“.+”匹配字符串的“tr>aava</tr>ab”,在进行最大匹配时,它把两个“

二叉树的存储方式以及递归和非递归的三种遍历方式

树的定义和基本术语 树(Tree)是n(n>=0)个结点的有限集T,T为空时称为空树,否则它满足如下两个条件: (1)有且仅有一个特定的称为根(Root)的结点: (2)其余的结点可分为m(m>=0)个互不相交的子集T1,T2,T3-Tm,其中每个子集又是一棵树,并称其为子树(Subtree). 树形结构应用实例: 1.日常生活:家族谱.行政组织结构:书的目录 2.计算机:资源管理器的文件夹: 编译程序:用树表示源程序的语法结构: 数据库系统:用树组织信息: 分析算法:用树来描述其执行过程:

Binary Tree Inorder Traversal [leetcode] 非递归的三种解法

第一种方法是Morris Traversal 是O(n)时间复杂度,且不需要额外空间的方法.缺点是需要修改树. 通过将叶子节点的right指向其中序后继. 代码如下 vector<int> inorderTraversal(TreeNode *root) { vector<int> res; TreeNode * cur = root; TreeNode * pre = NULL; while (cur) { if (cur->left == NULL) { res.push

正则基础之——贪婪与非贪婪模式

转载自:http://blog.csdn.net/lxcnn/article/details/4756030 1        概述 贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配.非贪婪模式只被部分NFA引擎所支持. 属于贪婪模式的量词,也叫做匹配优先量词,包括: “{m,n}”.“{m,}”.“?”.“*”和“+”. 在一些使用NFA引擎的语言中,在匹配优先量词后加上“?”

python 正则贪婪模式和非贪婪模式

贪婪模式:在表达式匹配成功的前提下,总是尽可能多的匹配字符飞天蓝模式:在表达式匹配成功的前提下,总是尽量少的匹配字符 1 # !/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 5 def test(): 6 string = "abc123456789sdsddskcas" 7 print "a(.*)c贪婪模式匹配结果:" 8 print re.findall(r"a(.*)c&quo

正则贪婪和非贪婪

? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的.非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串.例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'.