正则表达式的回溯

现在我们来正式认识一下回溯。以字符串“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. codeforce F - Three Paths on a Tree

    F. Three Paths on a Tree time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  2. 随笔js

    js中的函数定义之后,函数名就是这个函数(JS中函数其实也是对象)的地址(句柄) js读取函数内存地址: 首先想读内存地址只有C或者C++,汇编抛开不谈,其他高级语言一般都封装起来了,不过我也不能确定 ...

  3. golang中的net/rpc包

    本文先介绍RPC,然后go原生对RPC的使用,之后是介绍go语言中有哪些RPC框架以及一些其他常见的框架,最后是探究go语言中rpc的源码. (1)首先介绍下什么RPC? (2)RPC可以做什么? ( ...

  4. vue项目接入markdown

    vue 项目接入 markdown 最近做一个项目,需要在vue项目中接入 markdown 编辑器,其实这个好接,他没有什么特别的样式,男的就是图片的上传. 今天给大家推荐一个插件 :mavonEd ...

  5. Thinkphp中验证码不显示解决办法

    1.页面是否存在bom头, 2.入口文件中是否有define(‘APP_DEBUG’, TRUE); //是否开启调试模式,上线时请改为false

  6. 7_4 素数环(UVa524)<回溯法和生成-测试法的比较>

    有一个环(ring)是由n个圈圈所组成的(在这里n一定是个偶数),我们想要把1到n的自然数各放到一个圈圈中,使得相邻2个圈圈中的数的和一定是素数.下图为n=6的情形.请注意:第1个圈圈中的数一定是1. ...

  7. javaWeb核心技术之分页和条件

    分页:limit ?,? 参数1 : startIndex 开始索引. 参数2 : pageSize 每页显示的个数 n 表示第几页 给定一个特殊的单词 pageNumber select * fro ...

  8. PowerDesigner--comment和name互相复制

    1.comment复制到name 脚本代码: Option Explicit ValidationMode = True InteractiveMode = im_Batch Dim mdl Set ...

  9. php 移动操作数组函数

    下面的几个主要是移动数组指针和压入弹出数组元素的和个函数. 函数 功能 array_shift 弹出数组中的第一个元素 array_unshift 在数组的开始处压入元素 array_push 向数组 ...

  10. 部署DVWA时的一些问题和解决办法(一)

    第一个有可能遇到的问题 0x4 配置PHP 配置PHP,GD支持 系统从2017更新到2018多个php版本共存问题解决,phpinfo 显示7.0 ,而php -v 显示7.2问题 apt-get ...