正则之坑知多少

原文地址: 又双叒叕学习了一遍正则表达式

前两天在 Twitter 上看到了题图,感觉又是个大坑,在此介绍正则本身和在 JavaScript 中使用正则的坑。如有错误,烦请指正。

首先说说 JavaScript 中正则的坑。

字面量 VS RegExp()

在 JavaScript 中创建正则表达式有两种方式:

// 正则字面量
var pattern1 = /\d+/;
​
// 构造 RegExp 实例,以字符串形式传入正则
var pattern2 = new RegExp('\\d+'); 

两种方式创建出的正则没有任何差别。从创建方式上看,正则字面量可读性更优,因为正则中经常使用 \ 反斜杠在字符串中是一个转义字符,想以字符串中表示反斜杠的话,需要使用 \\ 两个反斜杠。

但是,需要注意,每个正则表达式都有一个独立的对象表示,每次创建正则表达式,都会为其创建一个新的正则表达式对象,这和其它类型(字符串、数组)不同

我们可以通过让正则表达式只编译一次并将其保存在一个变量中以供后续使用来实现优化。

因此,第一段代码将创建三个正则表达式对象,并进行了三次编译,虽然表达式是相同的。而第二段代码则性能更高。

console.log(/abc/.test('a'));
console.log(/abc/.test('ab'));
console.log(/abc/.test('abc'));
​
var pattern = /abc/;
console.log(pattern.test('a'));
console.log(pattern.test('ab'));
console.log(pattern.test('abc')); 

这其中有性能隐患。先记住这一点,我们继续往下看。

冷知识 lastIndex

这里我们来解释下题图中的情况是怎么回事。

这其实是全局匹配的坑,也就是正则后的 /g 符号。

var pattern = /abc/g;
console.log(pattern.global) // true 

/g 标识的正则作为全局匹配,也就拥有了 global 属性并导致了题图中呈现的异常行为。

全局正则表达式的另一个属性 lastIndex 用于存放上一次匹配文本之后的第一个字符的位置。

RegExp.prototype.exec()RegExp.prototype.test() 方法都以 lastIndex 属性中所存储的位置作为下次正则匹配检索的起点。连续调用这两个方法就可以遍历字符串中的所有匹配文本。

lastIndex 属性可读写,当 RegExp.prototype.exec()RegExp.prototype.test() 再也找不到可以匹配的文本时,会自动把 lastIndex 属性重置为 0。因此使用这两个方法来检索文本,是可以无限执行下去的。我们也就明白了题图中为何每次执行 RegExp.prototype.test() 返回的结果都不一样。

不仅如此,看看下面这段代码,能看出来有什么问题吗?

var count = 0;
while (/a/g.test('ababc')) count++; 

不要轻易拷贝到控制台中尝试,会把浏览器卡死的。

由于每个循环中 /a/g.test('ababc') 都创建了新的正则表达式对象,每次匹配都是重新开始,这一操作会无限执行下去,形成死循环。

正确的写法是:

var count = 0;
var regex = /a/g;
while (regex.test('ababc')) count++; 

这样,每次循环中操作的都是同一个正则表达式对象,随着每次匹配后 lastIndex 的增加,等到将整个字符串匹配完成后,就跳出循环了。

给以上知识点画个重点

1.将正则表达式保存到变量中,只在逻辑中使用这个变量,不仅性能更高,还安全。 2.谨慎使用全局匹配,RegExp.prototype.exec()RegExp.prototype.test()这两个方法的执行结果可能每次都不同。 3.做到了以上两点后,还要谨慎在循环中使用正则匹配。

回溯陷阱 Catastrophic Backtracking

回溯陷阱是正则表达式本身的一个坑了,会导致非常严重的性能问题,事故现场可以参看《一个正则表达式引发的血案,让线上 CPU100% 异常!》

简单介绍一下回溯陷阱的问题源头,正则引擎分为 NFA(确定型有穷自动机)DFA(不确定型有穷自动机)DFA 是从匹配文本入手,同一个字符不会匹配两次(可以理解为手里捏着文本,挨个字符拿去匹配正则),时间复杂度是线性的,它的功能有限,不支持回溯。大多数编程语言选用的都是 NFA,相当于手里拿着正则表达式,去匹配文本。

/(a(bdc|cbd|bcd)/ 中已经有三种匹配路径,在 NFA 中,以文本 'abcd' 为例,将花费 7 步才能匹配成功:

(图中还包括了字符边界的匹配步骤,因此多了三步)

1.正则中的第一个字符 a 匹配到 'abcd' 中的第一个字母 'a',匹配成功。 2.此时遇到了匹配路径的分叉口,bdc 或 cbd 或 bcd,先使用 bdc 来匹配。 3.bdc 中的第一个字符 b 匹配到了 'abcd' 中的第二个字母 'b',匹配成功。 4.bdc 中的第二个字符 d 与 'abcd' 中的第三个字母 'c' 不匹配,这条路径匹配失败,此时将发生回溯(backtrack),把 'b' 还回去。选择第二条路径 cbd 进行匹配。 5.cbd 的第一个字符 'c' 就与 'b' 匹配失败。开始第三条路径 bcd 的匹配。 6.bcd 的第一个字符 'b' 与文本 'b' 匹配成功。 7.bcd 的第一个字符 'c' 与文本 'c' 匹配成功。 8.bcd 的第一个字符 'd' 与文本 'd' 匹配成功。

至此匹配完成。

可想而知,如果正则中再多一些匹配路径或者匹配本文再长一点,匹配步骤将多到难以控制。

比如用 /(a*)*bc/ 来匹配 'aaaaaaaaaaaabc' 都会导致性能问题,匹配文本中每增加一个 'a',都会导致执行时间翻倍。

禁止这种回溯陷阱的方法有两种:

1.占有优先量词(Possessive Quantifiers) 2.原子分组(Atomic Grouping)

可惜 JavaScript 不支持这两种语法,有兴趣可以 Google 自行了解下。

在 JavaScript 中我们没有方法可以直接禁止回溯陷阱,我们只能:

1.避免量词嵌套 (a*)* => a* 2.减少匹配路径

除此之外,我们也可以把正则匹配放到 Service Worker 中进行,从而避免影响页面性能。

网络安全入门学习路线

其实入门网络安全要学的东西不算多,也就是网络基础+操作系统+中间件+数据库,四个流程下来就差不多了。

1.网络安全法和了解电脑基础

其中包括操作系统Windows基础和Linux基础,标记语言HTML基础和代码JS基础,以及网络基础、数据库基础和虚拟机使用等...

别被这些看上去很多的东西给吓到了,其实都是很简单的基础知识,同学们看完基本上都能掌握。计算机专业的同学都应该接触了解过,这部分可以直接略过。没学过的同学也不要慌,可以去B站搜索相关视频,你搜关键词网络安全工程师会出现很多相关的视频教程,我粗略的看了一下,排名第一的视频就讲的很详细。 当然你也可以看下面这个视频教程仅展示部分截图 学到http和https抓包后能读懂它在说什么就行。

2.网络基础和编程语言

3.入手Web安全

web是对外开放的,自然成了的重点关照对象,有事没事就来入侵一波,你说不管能行吗! 想学好Web安全,咱首先得先弄清web是怎么搭建的,知道它的构造才能精准打击。所以web前端和web后端的知识多少要了解点,然后再学点python,起码得看懂部分代码吧。

最后网站开发知识多少也要了解点,不过别紧张,只是学习基础知识。

等你用几周的时间学完这些,基本上算是具备了入门合格渗透工程师的资格,记得上述的重点要重点关注哦! 再就是,要正式进入web安全领域,得学会web渗透,OWASP TOP 10等常见Web漏洞原理与利用方式需要掌握,像SQL注入/XSS跨站脚本攻击/Webshell木马编写/命令执行等。

这个过程并不枯燥,一边打怪刷级一边成长岂不美哉,每个攻击手段都能让你玩得不亦乐乎,而且总有更猥琐的方法等着你去实践。

学完web渗透还不算完,还得掌握相关系统层面漏洞,像ms17-010永恒之蓝等各种微软ms漏洞,所以要学习后渗透。可能到这里大家已经不知所云了,不过不要紧,等你学会了web渗透再来看会发现很简单。

其实学会了这几步,你就正式从新手小白晋升为入门学员了,真的不算难,你上你也行。

4.安全体系

不过我们这个水平也就算个渗透测试工程师,也就只能做个基础的安全服务,而这个领域还有很多业务,像攻防演练、等保测评、风险评估等,我们的能力根本不够看。

所以想要成为一名合格的网络工程师,想要拿到安全公司的offer,还得再掌握更多的网络安全知识,能力再更上一层楼才行。即便以后进入企业,也需要学习很多新知识,不充实自己的技能就会被淘汰。

从时代发展的角度看,网络安全的知识是学不完的,而且以后要学的会更多,同学们要摆正心态,既然选择入门网络安全,就不能仅仅只是入门程度而已,能力越强机会才越多。

尾言

因为入门学习阶段知识点比较杂,所以我讲得比较笼统,最后联合CSDN整理了一套【282G】网络安全从入门到精通资料包,需要的小伙伴可以点击链接领取哦! 网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《正则表达式必知必会pdf》是一本关于正则表达式的学习资料。正则表达式(Regular Expression,简称Regex)是一种高级的字符串匹配工具,广泛应用于文本处理、搜索引擎、数据清洗等领域。这本PDF提供了学习正则表达式的基本知识和实例应用。 首先,这本PDF会从正则表达式的基础开始介绍,包括元字符(metacharacters)、字符类(character class)、重复限定符(repetition qualifier)等。它会教你如何使用这些元素来构建具有特定匹配规则的表达式。 其次,PDF会详细介绍正则表达式的常见应用场景,比如提取URL、邮箱地址、手机号码等。它通过实例演示了如何利用正则表达式来完成这些任务,帮助你更好地理解和掌握正则表达式的使用方法。 此外,这本PDF还会讲解一些高级的正则表达式技巧,比如分组和捕获、反向引用等。这些技巧可以进一步提升你处理复杂文本的能力,让你能够更加灵活地应用正则表达式。 总的来说,《正则表达式必知必会pdf》是一本系统全面介绍正则表达式的学习资料。它不仅适合初学者入门,也适合有一定经验的开发人员深入学习。通过学习这本PDF,你可以更加熟练地运用正则表达式,提高文本处理的效率和准确性。 ### 回答2: 《正则表达式必知必会.pdf》是一本关于正则表达式的指南,它是为那些希望学习和掌握正则表达式的人们而设计的。 首先,正则表达式是一种强大的文本匹配工具,它可以用来在文本中查找、替换和验证特定的模式。这在计算机编程和数据处理领域中非常有用。《正则表达式必知必会.pdf》通过简明易懂的方式,介绍了正则表达式的基础知识和常用的语法规则。 在这本书中,作者首先介绍了正则表达式的基本概念,如字符、元字符、字符类和量词等。然后,他详细讲解了如何使用正则表达式进行模式匹配和替换操作。通过大量的实例和练习,读者可以逐步理解和掌握正则表达式的使用方法。 除了基本的语法规则外,这本书还介绍了一些高级的技巧和实用的应用场景。例如,如何在正则表达式中使用分组、引用和捕获;如何处理特殊字符和转义序列等。这些内容可以帮助读者更好地应对各种复杂的文本处理需求。 总的来说,《正则表达式必知必会.pdf》是一本很好的入门教材。它将复杂的概念和技巧以简洁明了的方式呈现出来,适合各个层次的读者阅读和学习。无论是初学者还是有经验的开发人员,都可以从中获得很大的帮助并提高他们的文本处理能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值