全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

正则中的回溯定义与用法分析【JS与java实现】

本文实例分析了正则中的回溯定义与用法。分享给大家供大家参考,具体如下:

关于“回溯”我也是第一次接触,对它也不算很了解。下面就把我所了解的做为一个心德记录下来,以备查看。

我们所使用的正则表达式的匹配基础大概分为:优先选择最左端(最靠开头)的匹配结果和标准的匹配量词(*、+、?和{m, n})是匹配优先的。

“优先选择最左端的匹配”顾名思义就是从字符串的起始位置开始匹配直到匹配结束这是基础;“标准匹配量词”又分为“非确定型有穷自动机(NFA)”也可以叫做“表达式主导”;另外一种是“确定型有穷自动机(DFA)”也可以叫做“文本主导”。我们目前在JavaScript中所使用的正则表达式为“表达式主导”。表达式主导和文本主导解释起来有些麻烦,先看来一个例子可能会清楚些。

// 使用正则表达式匹配文本
var reg = /to(nite|knight|night)/;
var str = 'doing tonight';
reg.test(str);

在上面的这个例子中,第一个元素[t],它将会重复尝试,直到目标字符串中找到‘t'为止。之后,就检查紧随其后的字符是否能由[o]匹配,如果能,就检查下面的元素(nite|knight|night)。它的真正含义是“nite”或者“knight”或者“night”。引擎会依次尝试这3种可能。尝试[nite]的过程是先尝试[n],然后[i],然后[t],最后是[e]。如果这种尝试失败,引擎会尝试另一种可能,如此继续下去,直到匹配成功或是报告失败。表达式中的控制权在不同的元素之间转换,所以称为“表达式主导”。

同样是上面的例子“文本主导”在扫描字符串时,会记录当前有效的所有匹配可。当引擎移动到t时,它会在当前处理的匹配可能中添加一个潜在的可能:

字符串中的位置 正则表达中的位置
……doing tonight 可能的匹配位置:/to(nite|knight|nigth)/

接下来扫描的每个字符,都会更新当前的可能匹配序列。继续扫描两个字符以后的情况是:

字符串中的位置 正则表达中的位置
……doing tonight 可能的匹配位置:/to(nite|knight|nigth)/

有效的可能匹配变为两个(knight被淘汰出局)。扫描到g时,就只剩下一个可能匹配了。当h和t匹配完成后,引擎发现匹配已经完成,报告成功。“文本主导”是因为它扫描的字符串中的每个字符都对引擎进行了控制。

如果想要弄明白“表达式主导”是如何工作的,那就要看一下我们今天的主题“回溯(backtracking)”。回溯就像是在走岔路口,当遇到岔路的时候就先在每个路口做一个标记。如果走了死路,就可以照原路返回,直到遇见之前所做过的标记,标记着还未尝试过的道路。如果那条路也走不能,可以继续返回,找到下一个标记,如此重复,直到找到出路,或者直到完成所有没有尝试过的路。

在许多情况下,正则引擎必须在两个(或更多)选项中做出选择。当遇到/……x?……/时,引擎必须是否尝试匹配X。对于/……X+……/的情况,毫无疑问,X至少尝试匹配一次——因为加号要求必须匹配至少一次。第一个X匹配之后,此要求已经满足,需要决定是否尝试下一个X。如果决定进行,还要决定是否匹配第三个X,第四个X,如此继续。每次选择,其实就是做一个标记,用于提示此处还有另一个可能的选择,保留起来以备用。在回溯的过程中要考虑两个要点:哪个分支应当首先选择?回溯的时候使用的是哪个(或者是哪些个)之前保存的分支?

第一个问题是按下面这条重要原则来选择的:

如果需要在“进行尝试”和“路过尝试”之间选择,对于匹配优先量词,引擎会优先选择“进行尝试”,而对于忽略优先量词,会选择“路过尝试”。

第二个问题是按以下这条原则:

距离当前最近储存的选项就是当本地失败强制回溯时返回的。使用的原则是LIFO(last in first out,后进先出)。

我们先来看几个在道路中做标记的例子:

1、未进行回溯的匹配

用[ab?c]来匹配“abc”。[a]匹配之后,匹配的当前状态如下:
“abc” ab?c

现在轮到[b?]了,正则引擎需要决定:是需要尝试[b]呢,还是跳过?因为[?]是匹配优先的,它会尝试匹配。但是,为了确保在这个尝试最终失败之后能够恢复,引擎会把:
“abc” ab?c

添加到备用状态序列中。也就是说,稍后引擎可能从下面的位置继续匹配:从正则表达式中的[b?]之后,字符串的c之前(也就是说当前的位置)匹配。这实际上就是跳过[b]的匹配,而问题容许这样做。引擎做好标记后,就会继续向前检查[b]。在示例中,它能够匹配,所以新的当前状态变为:

“abc” ab?c

最终的[c]也能成功匹配,所以整个匹配完成。备用状态不再需要了,所以不再保存它们。

2、进行了回溯的匹配

下面要匹配的文本是“ac”,在尝试[b]之前,一切都与之前的过程相同。显然,这次[b]无法匹配。也就是说,对[……?]进行尝试的路走不通了。因为有一个备用状态,这个“局部匹配失败”产工会导致整体匹配失败。引擎会进行回溯,也就是说,把“当前状态”切换为最近保存的状态。
“ac” ab?c

在[b]尝试之前保存的尚未尝试的选项。这时候,[c]可以匹配c,所以整个匹配宣告完成。

3、不成功的匹配

现在要匹配的文本是“abx”。在尝试[b]以前,因为存在问号,保存了这个备用状态:
“abx” ab?c

[b]能够匹配,但这条路往下却走不通了,因为[c]无法匹配x。于是引擎会回溯到之前的状态,“交还”b给[c]来匹配。显然,这次测试也失败了。如果还有其他保存的状态,回溯会继续进行,但是此时不存在其他状态,在字符串中当前位置开始的整个匹配也就宣告失败。

例子1: 提取字符串   提取 da12bka3434bdca4343bdca234bm   提取包含在字符a和b之间的数字,但是这个a之前的字符不能是c,b后面的字符必须是d才能提取。

例如这里就只有3434这个数字满足要求。那么我们怎么提取呢?

首先我们写出提取这个字符串的表达式: (?<!c)a(/d+)bd  这里就只有一个捕获组(/d+)

Java代码片段如下:

Pattern p = Pattern.compile( "(?<!c)a(//d+)bd " );
Matcher m = p.matcher( "da12bka3434bdca4343bdca234bm" );
 while (m.find()){
 System.out.println(m.group( 1 )); //我们只要捕获组1的数字即可。结果 3434
 System.out.println(m.group(0)); // 0组是整个表达式,看这里,并没有提炼出(?<!c)的字符 。结果 a3434bd
}

例子2: 将一些多位的小数截短到三位小数:\d+\.\d\d[1-9]?\d+

在这种条件下 6.625 能进行匹配,这样做没有必要,因为它本身就是三位小数。最后一个“5”本来是给 [1-9] 匹配的,但是后面还有一个 \d+ 所以,[1-9] 由于是“?”可以不匹配所以只能放弃当前的匹配,将这个“5”送给 \d+ 去匹配,如果改为:

\d+\.\d\d[1-9]?+\d+

的侵占形式,在“5”匹配到 [1-9] 时,由于是侵占式的,所以不会进行回溯,后面的 \d+ 就匹配不到任东西了,所以导致 6.625 匹配失败。

这种情况,在替换时就有效了,比如把数字截短到小数点后三位,如果正好是三位小数的,就可以不用替换了,可以提高效率,侵占量词基本上就是用来提高匹配效率的。

把 \d+\.\d\d[1-9]?+\d+ 改为 \d+\.\d\d(?>[1-9]?)\d+ 这样是一样的。

PS:这里再为大家提供2款非常方便的正则表达式工具供大家参考使用:

JavaScript正则表达式在线测试工具:
http://tools./regex/javascript

正则表达式在线生成工具:
http://tools./regex/create_reg

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript正则表达式技巧大全》、《JavaScript替换操作技巧总结》、《JavaScript查找算法技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》、《JavaScript中json操作技巧总结》、《JavaScript错误与调试技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。


# 正则  # 回溯  # JS  # java  # 如何基于java语言实现八皇后问题  # Java基于循环递归回溯实现八皇后问题算法示例  # java实现八皇后问题示例分享  # java回溯算法解数独问题  # Java实现走迷宫回溯算法  # java使用回溯法求解数独示例  # 浅谈Java实现回溯算法之八皇后问题  # 宋体  # 正则表达式  # 第一个  # 也就是说  # 左端  # 这条  # 这样做  # 问题是  # 做一个  # 条路  # 跳过  # 进行了  # 就可以  # 的是  # 这是  # 操作技巧  # 几个  # 就会  # 是在  # 就像 


相关文章: 学校建站服务器如何选型才能满足性能需求?  怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?  网站企业制作流程,用什么语言做企业网站比较好?  css网站制作参考文献有哪些,易聊怎么注册?  建站之星备案流程有哪些注意事项?  香港网站服务器数量如何影响SEO优化效果?  如何在建站主机中优化服务器配置?  网站app免费制作软件,能免费看各大网站视频的手机app?  如何在阿里云通过域名搭建网站?  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  建站主机SSH密钥生成步骤及常见问题解答?  建站之星安装后如何配置SEO及设计样式?  如何用y主机助手快速搭建网站?  TestNG的testng.xml配置文件怎么写  如何配置WinSCP新建站点的密钥验证步骤?  c++怎么用jemalloc c++替换默认内存分配器【性能】  如何通过宝塔面板实现本地网站访问?  代刷网站制作软件,别人代刷火车票靠谱吗?  在线制作视频的网站有哪些,电脑如何制作视频短片?  如何在阿里云高效完成企业建站全流程?  昆明网站制作哪家好,昆明公租房申请网上登录入口?  大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?  建站之星安装失败:服务器环境不兼容?  网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?  建站之家VIP精选网站模板与SEO优化教程整合指南  GML (Geography Markup Language)是什么,它如何用XML来表示地理空间信息?  免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?  网站设计制作公司地址,网站建设比较好的公司都有哪些?  香港服务器如何优化才能显著提升网站加载速度?  较简单的网站制作软件有哪些,手机版网页制作用什么软件?  教育培训网站制作流程,请问edu教育网站的域名怎么申请?  如何构建满足综合性能需求的优质建站方案?  建站主机默认首页配置指南:核心功能与访问路径优化  详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)  电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?  电商网站制作公司有哪些,1688网是什么意思?  合肥做个网站多少钱,合肥本地有没有比较靠谱的交友平台?  如何零成本快速生成个人自助网站?  实惠建站价格推荐:2025年高性价比自助建站套餐解析  已有域名和空间如何搭建网站?  如何登录建站主机?访问步骤全解析  网页设计与网站制作内容,怎样注册网站?  如何选择网络建站服务器?高效建站必看指南  如何在Golang中处理模块冲突_解决依赖版本不兼容问题  学校免费自助建站系统:智能生成+拖拽设计+多端适配  网站制作公司排行榜,抖音怎样做个人官方网站  如何通过商城免费建站系统源码自定义网站主题?  在线ppt制作网站有哪些,请推荐几个好的课件下载的网站?  如何通过建站之星自助学习解决操作问题?  高防服务器租用指南:配置选择与快速部署攻略 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。