Heim > Web-Frontend > js-Tutorial > Hauptteil

怎么快速掌握正则表达式?通过 AST 来学学正则语法!

青灯夜游
Freigeben: 2022-03-09 20:13:59
nach vorne
2042 人浏览过

正则表达式是对字符串操作的一种逻辑公式,是在处理文本数据时的一项重要而复杂的技术。那么怎么快速掌握正则表达式?下面本篇文章推荐一种学习方法:通过 AST。希望对大家有所帮助!

怎么快速掌握正则表达式?通过 AST 来学学正则语法!

字符串的处理基本都会用正则表达式,用它来做字符串的匹配、提取、替换等很方便。

但是正则表达式的学习还是有些难度的,比如贪婪匹配、非贪婪匹配、捕获子组、非捕获子组等概念,不止初学者难理解,有很多工作几年的人都不理解。

那正则表达式怎么学比较好?怎么快速掌握正则表达式呢?

推荐一个我觉得很不错的学习正则的方式:通过 AST 来学习

正则表达式的匹配原理是把模式串 parse 成 AST,然后通过这个 AST 去匹配目标字符串。

模式串中的各种信息在 parse 之后都会保存在 AST 里面。AST 是 abstract syntax tree,抽象语法树的意思,顾名思义,是按照语法结构组织的一棵树,那么从 AST 的结构上自然可以轻易的知道正则表达式支持的语法。

怎么查看正则表达式的 AST 呢?

可以通过 astexplorer.net 这个网站来可视化的查看:

1.png

切换 parse 的语言为 RegExp,就可以做正则表达式的 AST 的可视化。

就像前面所说,AST 是按照语法来组织的一棵树,那么从它的结构上自然能容易地理清各种语法。

那么我们就从 AST 的角度来学习下各种语法吧:

/abc/

先从简单的开始,/abc/ 这样一个正则就可以匹配 'abc' 的字符串,它的 AST 是这样的:

2.png

3 个 Char,值分别是 a、b、c,类型是 simple。那之后的匹配就是遍历 AST,分别匹配这三个字符了。

我们用 exec 的 api 测试了下:

3.png

第 0 个元素是匹配的字符串,index 是匹配字符串的开始下标。input 是输入的字符串。

再来试下特殊的字符:

/\d\d\d/

/\d\d\d/ 是匹配三个数字的意思,\d 是正则支持的有特殊含义的元字符(meta char)。

通过 AST 我们也可以看出来,它们虽然也是 Char,但类型确是 meta:

4.png

可以通过 \d 的元字符来匹配任意数字:

5.png

哪些是 meta char 哪些是 simple char,通过 AST 来看一目了然。

/[abc]/

正则支持通过 [] 的方式来指定一组字符,也就是说匹配其中任意一种字符都行。

通过 AST 我们也可以看出来,它被包裹了一层 CharacterClass,就是字符类的意思,也就是匹配它包含的任意一种字符都行。

6.png

测试下也确实是这样:

7.png

/a{1,3}/

正则表达式支持指定某个字符重复多少次,用 {from,to} 的形式,

比如 /b{1,3}/ 表示字符 b 重复 1 到 3 次,/[abc]{1,3}/ 表示这个 a/b/c 字符类重复 1 到 3 次。

通过 AST 可以看出来,这种语法叫做 Repetition(重复):

8.png

他有个 quantifier 的属性表示量词,这里的类型是 range,从 1 到 3。

正则也支持一些量词的简写,比如 + 表示 1 到无数次、* 表示 0 到无数次、? 表示 0 或 1 次。

分别是不同类型的量词:

9.png

有同学可能会问,这里的 greedy 属性是啥意思呢?

10.png

greedy 是贪婪的意思,这个属性就表示这个 Repetition 是贪婪匹配还是非贪婪匹配。

如果在量词后加个 ?,你就会发现 greedy 变成 false 了,也就是切换到了非贪婪匹配:

11.png

那贪婪和非贪婪是指啥呢?

我们看个例子就知道了。

12.png

默认 Repetition 的匹配是贪婪的,只要满足条件就一直匹配下去,所以这里 acbac 都能匹配到。

量词后加个 ? 就切换到了非贪婪,就只会匹配第一个了:

13.png

这就是贪婪匹配和非贪婪匹配,通过 AST 我们能够清楚的知道贪婪和非贪婪是针对重复语法来说的,默认是贪婪匹配,在量词后加个 ? 就可以切换到非贪婪。

(aaa)bbb(ccc)

正则表达式支持通过()把匹配到的一部分字符串放到子组里返回。

通过 AST 看一下:

14.png

对应的 AST 就叫做 Group。

而且你会发现它有个 capturing 的属性,默认是 true:

15.png

这是啥意思呢?

这就是子组捕获的语法。

如果不想捕获子组,可以这样写 (?:aaa)

16.png

看,capturing 变为 false 了。

那捕获和非捕获有什么区别呢?

我们试一下:

17.png

哦,原来 Group 的 capturing 属性代表的是是否提取的意思啊。

我们通过 AST 可以看出来,捕获是针对子组来说的,默认是捕获,也就是提取子组的内容,可以通过 ?: 切换到非捕获,就不会提取子组的内容了。

我们对用 AST 来了解正则语法已经轻车熟路了,那来看点难的:

/bbb(?=ccc)/

正则表达式支持通过 (?=xxx) 的语法来表示先行断言,用来判断某个字符串是否前面是某个字符串。

通过 AST 可以看到这种语法叫做 Assertion,并且类型为 lookahead,也就是往前看,只匹配前面的意思:

18.png

这是啥意思呢?为啥要这么写?和 /bbb(ccc)/ 还有 /bbb(?:ccc)/有啥区别呢?

我们试一下:

19.png

从结果可以看出来:

/bbb(ccc)/ 匹配了 ccc 的子组并且提取出来了这个子组,因为默认子组是捕获的。

/bbb(?:ccc)/ 匹配了 ccc 的子组但没有提取出来,因为我们通过 ?: 设置了子组不捕获。

/bbb(?=ccc)/ 匹配了 ccc 的子组也没有提取出子组,说明也是非捕获的。它和 ?: 的区别是 ccc 没有出现在匹配结果里。

这就是先行断言(lookahead assertion)的性质:先行断言代表某段字符串前面是某段字符串,对应的子组是非捕获的,而且断言的字符串不会出现在匹配结果中。

如果后面不是跟着那段字符串就不匹配:

20.png

/bbb(?!ccc)/

把 ?= 改成 ?! 之后意思就变了,通过 AST 看一下:

21.png

虽然还是先行断言 lookahead assertion,但是多了个 negative 为 true 的属性。

这个意思很明显,本来是前面是某段字符串,否定之后就是前面不是某段字符串。

那匹配结果正好就反过来了:

22.png

现在前面不是某段字符串的话才匹配了,这就是否定先行断言。

/(?<=aaa)bbb/

有先行断言自然也有后行断言,也就是后面是某段字符串才匹配。

23.png

同理,也可以否定:

24.png

(?<=aaa)对应的 AST 很容易想到,就是 lookbehind assertion:

25.png

(?

26.png

先行断言、后行断言就是最难理解的正则表达式语法了,通过 AST 来学习是不是就容易理解多了~

总结

正则表达式是处理字符串的很方便的工具,但它的学习还是有些难度的,像贪婪匹配、非贪婪匹配、捕获子组、非捕获子组、先行断言、后行断言等语法很多人都搞不清楚。

我推荐通过 AST 来学习正则,AST 是按照语法结构来组织的一颗对象树,各种语法通过 AST 节点的名字和属性可以轻易的理清楚。

比如我们通过 AST 理清楚了:

重复语法(Repetition)就是字符 + 量词的形式,默认是贪婪匹配(greedy 为 true),代表一直匹配到不匹配为止,量词后加个 ? 就切换成了非贪婪匹配,匹配到一个字符就停止。

子组语法(Group)是用于提取某段字符串的,默认是捕获(capturing 为 true),代表需要提取,可以通过 (?:xxx)切换到非捕获,只匹配不提取。

断言语法(Assertion)代表前面或后面有某段字符串,分为先行断言(lookahead assertion)和后行断言(lookbehind assertion),语法分别是(?=xxx)和 (?<=xxx),可以通过把 = 换成 ! 来表示否定(negative 为 true),意思正好反过来。

是各种文档对语法理解的深还是编译器对语法理解的深?

那还用问,肯定是编译器呀!

那么通过它按照语法 parse 出来的语法树来学习语法自然比文档更好。

正则表达式是这样,其他的语法的学习也是这样,能用 AST 学会的语法,就不需要看文档。

更多node相关知识,请访问:nodejs 教程

以上是怎么快速掌握正则表达式?通过 AST 来学学正则语法!的详细内容。更多信息请关注PHP中文网其他相关文章!

Verwandte Etiketten:
Quelle:juejin.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!