资讯专栏INFORMATION COLUMN

读《精通正则表达式》-- 网上 js 正则基础教程没有涉及的一些知识

GT / 2664人阅读

摘要:正则起源最近看完了精通正则表达式,收获颇丰,略过了一些晦涩难懂的理论部分,主要看了实战和教程部分。然后下面说一下以上两个基础教程里没说到的知识点。最后以上是我在精通正则表达式一书中得到的一些收获,希望能分享给大家,如有错误欢迎指正。

正则起源

最近看完了 《精通正则表达式》,收获颇丰,略过了一些晦涩难懂的理论部分,主要看了实战和教程部分。

下面引用一下百度百科里的内容。

正则表达式的“鼻祖”或许可一直追溯到科学家对人类神经系统工作原理的早期研究。美国新泽西州的Warren McCulloch和出生在美国底特律的Walter Pitts这两位神经生理方面的科学家,研究出了一种用数学方式来描述神经网络的新方法,他们创造性地将神经系统中的神经元描述成了小而简单的自动控制元,从而作出了一项伟大的工作革新。

那么写正则是不是就是把自己神经工作过程通过正则表现出来呢? 比如让小孩子在一堆图形中找到匹配的图形放入凹槽。

正则引擎

正则分几种引擎也从是本书获得的知识点之一。

DFA

传统型NFA

POSIX NFA

NFA范围更广,例如 JAVA, PHP, Ruby, .NET... 你是看不起我javascript所以才不列入的吗?

使用DFA的是flex, MySQL, lex, awk大部分版本… 实话说,除了mysql,都没听过。不过不用在意!

两个引擎的区别。

NFA 更注重表达式

DFA 文本主导

通过书中里例子说,NFA 用表达式来匹配文本,而 DFA 是文本来匹配文表达式。当写好一个正则之后,NFA 是先检查表达式,同时检查文本是否匹配这个表达式。而 DFA 则是先扫描文本,然后处理表达式中的所有匹配可能,如果匹配失败,就将这条可能的线,淘汰。所以这里衍生一个概念就是回溯,NFA 有回溯,而 DFA 没有。

知识点

作为一个菜鸟,正则表达式一直是书到用时方恨少的角色。平时都是能抄则抄,不能抄的时候干着急,只能用 substr, indexOf, chatAt等等的方法实现功能,既不优雅也不够装逼。上网学习也都是菜鸟教程,W3school。然后下面说一下以上两个基础教程里没说到的知识点。

括号捕获与反向引用

当你在正则表达式里使用了 (),在表达式匹配时,它能记住或者说缓存括号内匹配的结果,从而可以拿到括号内的结果,可以重复使用或者只需要括号内的结果,来剔除不需要的匹配内容。

// 我们经常会用 match 方法来匹配字符串,结果是一个数组,而不是最后的匹配结果,为什么呢?看下面的例子
"abc".match(/(a)(b)(c)/) // ["abc", "a", "b", "c"]
"abc".match(/abc/) // ["abc"]

可以看到,括号会缓存括号里匹配的内容,多带带列出来,那么怎么拿到括号内的内容呢,而不是通过 match 返回的结果拿,因为有时候我们需要在表达式里使用捕获的值,从而达到匹配重复的内容。这部分就叫反向引用

"abc-abc-cba".replace(/(a)(b)c-12/, "") // c-cba
"abc-abc-cba".replace(/(a)(b)c/g, "$1$2") // ab-ab-cba
RegExp.$1 // a
RegExp.$2 // b

这里展示了两种使用反向引用的方法,一种是在表达式内通过 12 的形式拿到两个缓存的值,一种是使用 $1$2的形式拿到。因为正则是从左开始匹配的,所以 (a) 就是第一个捕获的匹配值,所以他是1 或是 $1,以此类推。

非捕获型括号

上面说了括号会捕获值,一般来说这样会影响性能,或者你会用到括号来做分组,但是不想捕获的情况,(?:)非捕获型括号就是这么用的,那么重写一下上面的例子。

"abc-abc-cba".replace(/(a)(?:b)c-12/, "") // 匹配失败了,因为2不存在
"abc-abc-cba".replace(/(a)(?:b)c-1/, "") // bc-cba
RegExp.$1 // a
RegExp.$2 // ""
环视
类型 正则表达式
肯定逆序环视 ?<=
否定逆序环视 ?
肯定顺序环视 ?=
否定顺序环视 ?!

?=?! 在菜鸟和w3school 里有简单的提及,菜鸟里还提到这两个还能重写捕获,但是 ?<=? 并没有提及。

写几个 demo 表示一下:

// 找一个字母 a ,它紧跟在 b 前面
"abac".replace(/a(?=b)/g, "") // bac

// 找到一个字母 a ,它紧跟在一个不是 b 的字母前面
"abac".replace(/a(?!b)/g, "") // abc

// 接着是逆序环视
// 找到一个字母 a ,它跟在 b 后面
"abac".replace(/(?<=b)a/g, "") // abc

// 找到一个字母 a ,他不跟在 b 后面
"abac".replace(/(?

可以看出,环视是要和捕获括号一起用的,并且不会占用匹配字符,他只是检查表达式是否匹配。所以这就是重写捕获了。

忽略优先量词

量词匹配一般有三种 *+?。然而还可以写作, *?+? ,使匹配结果导向完全不同的结果。例子:

"abc-aaa-abc-abc".replace(/abc-.*-abc/, "") // ""

"abc-aaa-abc-abc".replace(/abc-.*?-abc/, "") // "-abc"

*? 忽略优先会先忽略当前匹配的值,先匹配后面的 -abc,如果匹配失败,再匹配自己,而 *会优先匹配自己,等匹配结束之后,再从后面一点点吐出,回来匹配量词后面的表达式。从而造成以上不同的结果。知道这个之后,就不会再傻傻的把 *? 分开解读了。当然,具体情况具体分析,到底使用哪个。

回溯

正则也是会有性能问题的,如果表达式写的不好,造成过度的灾难性回溯,会导致执行时间指数级增长。具体情况还是通过搜索引擎了解吧,解释起来会过长,而且作为正则新手的我还不一定能解释清楚。。。

最后

以上是我在《精通正则表达式》一书中得到的一些收获,希望能分享给大家,如有错误欢迎指正。下一步呢就是去做一些练习来巩固一下了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96608.html

相关文章

  • 正则达式

    摘要:本文内容共正则表达式火拼系列正则表达式回溯法原理学习正则表达式,是需要懂点儿匹配原理的。正则表达式迷你书问世了让帮你生成和解析参数字符串最全正则表达式总结验证号手机号中文邮编身份证地址等是正则表达式的缩写,作用是对字符串执行模式匹配。 JS 的正则表达式 正则表达式 一种几乎可以在所有的程序设计语言里和所有的计算机平台上使用的文字处理工具。它可以用来查找特定的信息(搜索),也可以用来查...

    bang590 评论0 收藏0
  • 基础 - 收藏集 - 掘金

    摘要:的语言的动态性意味着我们可以使用以上种数据类型表示变换过渡动画实现案例前端掘金以下所有效果的实现方式均为个人见解,如有不对的地方还请一一指出。 读 zepto 源码之工具函数 - 掘金Zepto 提供了丰富的工具函数,下面来一一解读。 源码版本 本文阅读的源码为 zepto1.2.0 $.extend $.extend 方法可以用来扩展目标对象的属性。目标对象的同名属性会被源对象的属性...

    wuaiqiu 评论0 收藏0
  • 前端资源系列(4)-前端学习资源分享&前端面试资源汇总

    摘要:特意对前端学习资源做一个汇总,方便自己学习查阅参考,和好友们共同进步。 特意对前端学习资源做一个汇总,方便自己学习查阅参考,和好友们共同进步。 本以为自己收藏的站点多,可以很快搞定,没想到一入汇总深似海。还有很多不足&遗漏的地方,欢迎补充。有错误的地方,还请斧正... 托管: welcome to git,欢迎交流,感谢star 有好友反应和斧正,会及时更新,平时业务工作时也会不定期更...

    princekin 评论0 收藏0
  • JavaScript系列(四) - 收藏集 - 掘金

    摘要:函数式编程前端掘金引言面向对象编程一直以来都是中的主导范式。函数式编程是一种强调减少对程序外部状态产生改变的方式。 JavaScript 函数式编程 - 前端 - 掘金引言 面向对象编程一直以来都是JavaScript中的主导范式。JavaScript作为一门多范式编程语言,然而,近几年,函数式编程越来越多得受到开发者的青睐。函数式编程是一种强调减少对程序外部状态产生改变的方式。因此,...

    cfanr 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<