正则表达式的回溯

现在我们来正式认识一下回溯。以字符串“abbc”为例,正则表达式为“ab{1,3}c”,再匹配的时候,a、b、b,匹配完成,这时候,正则表达式会继续用c和b进行比较,发现不符合,这时候就会产生回溯,也就是重新用c继续和正则表达式中的c进行比较,发现匹配成功,后续没有需要匹配的字符,完成匹配。 
我再把例子变一下,假设正则表达式还是“ab{1,3}c”,但是字符串变为“abbabc”,这时候,还是和上面一样,只不过再匹配到a、b、b后,匹配a发现与b(因为b可以是1到3个)不符合,这时候产生回溯一位,a继续与c比较,发现仍不匹配,这时候会直接回溯到最前面,即字符串中的第二个字符b再重新与正则表达式开始匹配,这时候的回溯位数就比较多了。

正则表达式的贪婪、懒惰和独占

上面举的例子,为什么已经匹配到b了,还要继续匹配b而不是直接匹配c了呢,这就是因为正则匹配默认是贪婪模式,也就是希望尽可能多的去匹配字符,所以正则表达式中写的b的个数为1到3个,那么它就会尽可能取匹配3个,不行才是2个,再不行才是1个。 
懒惰模式,就是尽可能少的匹配字符,所以上面那个例子会从1个b尝试,然后那c取匹配第二个字符,发现c与b不匹配,则回溯一位,用b{1,3}里的第二个b去匹配,然后接着再用c去匹配后面的字符。关键符号是“?”,即正则表达式变为“ab{1,3}?c” 
独占模式,正则表达式会尽可能长的进行匹配,一旦匹配错误也不会进行回溯。上面的例子来说,再b{1,3}这部分的时候,他会一次把后面最多3个b拿出来,但是后面只有两个b了,所以它也只能拿两个,结束后再进行c的比较,匹配成功。关键符号是“+”,即“ab{1,3}+c”。这里举个例子,如果正则表达式变为“ab{1,3}+bc”,这里正则表达式的区别是后面多了个b,由于独占模式b{1,3}的部分会尽可能多的匹配,所以b{1,3}会把文本中的两个b都匹配了,则后面继续匹配,b不等于c,由于独占模式也不回溯,所以匹配失败了。(这里如果没有“+”号的话,是会产生回溯可以匹配成功的)

总结

这里推荐一个验证正则表达式的网站:https://regex101.com/,他除了可以检查正则表达式的正确性以外,还能给出匹配步数,并且可以解析出正则表达式的解析步骤(右上角的EXPLANATION),还有更详细的匹配过程(左下角的regex debugger),还有很多例子regex,非常好用。 
最后还是给大家举个可能产生回溯陷阱的例子更容易理解吧。一般很多正则都会产生回溯,可能有个几十几百的步数还算正常,但是会产生回溯陷阱的一般都是无法匹配出来的,步数可能上完甚至几十万。正则表达式为“^(([a-zA-Z0-9]+).)+$”,字符串我就随便粘了一段比较长的网址,检测的就是字符串中是否是xxxx~xxxx|这种形式,就是一段[a-zA-Z0-9]字符串中间都要只有一个非[a-zA-Z0-9]的字符,如果有连续两个非[a-zA-Z0-9]的字符的话则匹配失败。(字符串举例“abcdekibana.xxxx.com/app/kibana#/discover/6530ca70-7467-11e8-8473-d1a78e1cb8f0?_g=(refreshInterval:('$$hashKey':'object:6533',display:Off,pause:!f,section:0,value:0),time:(from:now%2Fd,mode:quick,to:now%2Fd))&_a=(columns:!(vfdg,khg,tery,fgdg,fgdfs),filters:!(),index:fghyu98-6f97-11e8-be20-871a42a4e49a,interval:auto,query:(language: lucene,query:'dfgr:fjsdiouion7ee3%3D%3D'),sort:!('@timestamp',desc))”) 
通过上面提到的验证网站,会发现产生“Catastrophic Backtracking”提示,点开regex debugger就能看到回溯情况了。 
其实正则表达式大家用的很多了,一般用来检验用户名、邮箱、包含字符、url合法等。尤其是对于复杂的正则表达式来说一定要注意到使用的场景与具体回溯情况,如果会产生频繁回溯的正则表达式,那么就会掉入回溯陷阱,导致cpu飙高,严重回溯陷阱可能需要占用非常多的cpu时间,导致进程因为正则验证而假死,这点需要格外注意。

正则表达式regex回溯分析的更多相关文章

  1. C#正则表达式Regex常用匹配

    使用Regex类需要引用命名空间:using System.Text.RegularExpressions; 利用Regex类实现验证 示例1:注释的代码所起的作用是相同的,不过一个是静态方法,一个是 ...

  2. C#正则表达式Regex类的用法

    C#正则表达式Regex类的用法 更多2014/2/18 来源:C#学习浏览量:36891 学习标签: 正则表达式 Regex 本文导读:正则表达式的本质是使用一系列特殊字符模式,来表示某一类字符串, ...

  3. C#正则表达式Regex类

    C#正则表达式Regex类的使用 C#中为正则表达式的使用提供了非常强大的功能,这就是Regex类.这个包包含于System.Text.RegularExpressions命名空间下面,而这个命名空间 ...

  4. (四)boost库之正则表达式regex

    (四)boost库之正则表达式regex 正则表达式可以为我们带来极大的方便,有了它,再也不用为此烦恼 头文件: #include <boost/regex.hpp> 1.完全匹配 std ...

  5. boost 正则表达式 regex

    boost 正则表达式 regex   环境安装 如果在引用boost regex出现连接错误,但是引用其他的库却没有这个错误,这是因为对于boost来说,是免编译的,但是,正则这个库 是需要单独编译 ...

  6. 请写出正则表达式(regex),取得下列黄色部分的字符串 TEL: 02-236-9655/9659 FAX:02-236-9654 (黄色部分即02-236-9655/9659 ) ( 测试面试题)

    请写出正则表达式(regex),取得下列黄色部分的字符串 TEL: 02-236-9655/9659 FAX:02-236-9654 答: package test1; import java.uti ...

  7. Python 正则表达式(RegEx)

    版权所有,未经许可,禁止转载 章节 Python 介绍 Python 开发环境搭建 Python 语法 Python 变量 Python 数值类型 Python 类型转换 Python 字符串(Str ...

  8. 正则表达式(RegEx)官方手册/权威指南【Python】

    前言 正则表达式(称为RE,或正则,或正则表达式模式)本质上是嵌入在Python中的一种微小的.高度专业化的编程语言,可通过 re 模块获得. 使用这种小语言,你可以为要匹配的可能字符串集指定规则:此 ...

  9. C#正则表达式Regex类使用

    作为文本处理的利器——Perl语言对正则表达式的最强大支持起到了重要的作用,正因为如此,许多其他语言在加入正则表达式引擎的时候都会或多或少的兼顾perl风格的正则表达式,开发出相应的引擎.本人使用pe ...

随机推荐

  1. spring自动装配和通过java实现装配

    1.组建扫描 在类上添加注解@Component注解可以实现组建扫描 @Component public class A{ ... } 2.自动装配 通过在属性上或者方法上添加@Autowired注解 ...

  2. Linux下run文件的直接运行

    比如realplay.run 安装方法如下 chmod +x realplay.run ./realplay.run 然后他就会执行安装了,在过程中可能会要求你输入yes或no 安装完后就可以用了 , ...

  3. 隐写工具F5-steganography的使用

    1.git clone https://github.com/matthewgao/F5-steganography 2.进入F5-steganography-master文件夹,在空白处 ctrl+ ...

  4. http断点续传的原理

    ——————————————先讲原理,如下:—————————————————— 举一个详细的例子: 一般场景,要访问的域名:www.jizhuomi.com/android,文件名为down.zip ...

  5. Docker 进入正在运行的容器的4种方式

    在使用Docker创建了容器之后,如何进入该容器呢? 进入Docker容器比较常见的几种做法如下: 使用docker attach 使用SSH 使用nsenter 使用exec 一.使用docker ...

  6. [lua]紫猫lua教程-命令宝典-L1-03-01. 闭包

    L1[闭包]01. 函数的传递赋值 没什么说的 1.函数作为变量来看 可以轻松的声明 相互赋值 2.函数变量本质是 一个内存指针 所以函数变量的相互赋值不是传递的函数本身 而是指向这个函数的内存地址 ...

  7. 【C语言】用指针作为形参完成数据的升序排列

    #include<stdio.h> void sort(int *x,int n); int main() { ] = { ,,,,,,,,, },i; sort(arr, ); prin ...

  8. 【c++】零基础的自修课 01-开发工具的安装(code::blocks)

    1/开发工具的下载地址: ·(选用 visual studio开发工具,有区分mac和windows版本)https://visualstudio.microsoft.com/zh-hans/down ...

  9. ubuntu刪除軟件

    1.打开一个终端,输入dpkg --list ,按下Enter键,终端输出以下内容,显示的是你电脑上安装的所有软件2.在终端中找到你需要卸载的软件的名称,列表是按照首字母排序的.3.在终端上输入命令s ...

  10. 概率DP hdu 3366 .

    题意:一个人被困在一个城堡里,面前有n条路,他自己有m百万元,选择每一条路都有p概率通过,q概率遇到士兵,1-p-q概率道路不通:遇到士兵的话需要上交1百万,如果不够钱,则被杀死,问的是最优情况下多少 ...