正则表达式的回溯

现在我们来正式认识一下回溯。以字符串“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. PyInstaller用法

    pyinstaller定义:PyInstaller是一个压缩python文件成为可执行程序的一个软件. pyinstaller工作原理:① 它会扫描你所有的Python文档,并分析所有代码从而找出所有 ...

  2. Linux - Shell - #!/bin/bash

    概述 简单解释一下 shell 脚本卡头的 #!/bin/bash 水一篇, 少一篇 背景 shell 脚本中的注释 通常是 以# 卡头的行 但是有时候执行 shell 的时候, 会有这种内容 #!/ ...

  3. Docker - ubuntu 镜像安装网络工具

    概述 给 ubuntu 镜像, 安装一些基本的网络工具 背景 尝试学习的时候, 需要检测网络的连通性 没有这些工具, 绕了不少弯路 工具们 ping ip a 环境 docker 18.09 ubun ...

  4. 调用百度地图api隐藏版权信息

    调用百度地图API隐藏右下角版权信息 商用的话建议不要隐藏,避免侵权. 隐藏前: 隐藏后: .BMap_cpyCtrl { display: none; } .anchorBL { display: ...

  5. Python的深拷贝、浅拷贝

    浅拷贝 定义:浅拷贝只是对另外一个变量的内存地址的拷贝,这两个变量指向同一个内存地址的变量值. 浅拷贝的特点: 公用一个值: 这两个变量的内存地址一样: 对其中一个变量的值改变,另外一个变量的值也会改 ...

  6. H5实现查看图片和删除图片的效果

    在最近的项目中,H5需要实现查看图片和删除图片的效果,总结如下: 一.查看图片 查看图片使用weui的gallery.首先添加gallery的html,然后隐藏. <div class=&quo ...

  7. mnist 数据集的识别源码解析

    在基本跑完识别代码后,再来谈一谈自己对代码的理解: 1      前向传播过程文件(mnist_forward.py) 第一个函数get_weight(shape, regularizer); 定义了 ...

  8. 题解【SP1043】 GSS1 - Can you answer these queries I

    题目描述 You are given a sequence \(A_1, A_2, ..., A_n(|A_i|≤15007,1≤N≤50000)\). A query is defined as f ...

  9. Codeforces Round #622 (Div. 2)

    A: 题意: 有ABC的三种菜,现在有a个A,b个B,c个C,问能组成多少种不同菜单 思路: abc都大于等于4,肯定是7种,给abc排个序,从大到小举例删减 #include<bits/std ...

  10. toString()和toLocaleString()方法有什么区别和联系

    toString()和toLocaleString()有什么区别 偶然之间用到这两个方法 然后在数字转换成字符串的时候,并没有感觉这两个方法有什么区别,如下: 1 2 3 4 5 6 7 8 var  ...