来学习一下JS的正则表达式的用法。 C++中的正则采用的也是类似的规范。
目标文档是MDN的JS Guide的Regular expressions部分。
Regular expressions
正则表达式在JS中为RegExp标的。RegExp上有exec()和test()可以将正则应用于字符串。 字符串标的上则有match(), matchAll(), replace(), replaceAll(), search(), split()等方法可以用。
matchAll似乎是ES2020中引入的,参考ECMAScript - Introducing String “matchAll” Method in ES2020 (ES11),支持迭代的方式来获取匹配的部分。
Creating a regular expression
创建RegExp可以使用标的例现化的方式,比如new RegEx('a')
,或者使用//
来在措辞上指定正则:/ab+c/
。
Writing a regular expression pattern
正则的强大之处在于可以将语言的构成以样式(pattern)的形式表现出来,比如/d
表示数字。
样式有几类:
- Assertions,对匹配边界做一些确认
^
,匹配开头$
,匹配结尾\b
,匹配单词边界\B
,匹配非单词边界x(?=y)
,往前看一步,确认x后面跟着y,但是不把y列入匹配x(?!y)
, x后面不跟y(?<=y)x
,确认y在x前面,但是y不列入匹配(?<!y)x
,确认y不在x前面
- Character classes,用符号代表一类字符
- ‘.',万用字符匹配
- ‘\d’,数字匹配
- ‘\D’, 非数字匹配
- 其他诸如单词、空白、控制字符的匹配
- 还有Unicode码点、特性匹配
- Groups和ranges,把若干字符看出一体操作
x|y
,x或y[xyz]
,多个中任选一个,[^xyz]
多个中哪个都不选[a-c]
,连续多个中任选一个,[^a-c]
哪个都不选(x)
,记下对x的匹配,并给定下标,方便以后处理\n
,通过下标援引记下的匹配(?<Name>x)
,记下对x的匹配,并给定名字,方便以后处理\k<Name>
,通过名字援引记下的匹配(?:x)
,匹配x,但不记忆
- Qualifiers,对某个字符,给出需要匹配的数目
x*
,匹配字符x零到多次x+
,匹配字符x一到多次x?
,匹配字符x零次或单次x{n}
,匹配字符n次x{n,}
,匹配字符至少n次x{n,m}
,匹配字符从n到m的范围- 以上后面加
?
,比如x+?
,将匹配改成非贪婪匹配,/<.*?>/
只匹配some <foo> <bar> new </bar> </foo> thing
中的<foo>
- Unicode property escapes,针对Unicode的特殊处理
上面似乎没有提到字符序列的构成,比如xyz
代表一个x,y,z三字符序列。
Escaping
简单地说,用/
做转义字符。
Using parentheses
除非特别指定,引擎会记下括弧中匹配的内容。
Using regular expressions in JavaScript
用法:
- 看是否能够完全匹配一个字符串
- 部分匹配的话,返回匹配的内容,可以多次匹配,也可以只搜索匹配的内容
- 根据匹配做出替换、分拆等动作
Advanced searching with flags
d
,搜索时生成子字符串的索引g
,全局搜索i
,不在乎大小写m
,将字符串当作多行s
,.
可以匹配换行u
,将样式当作统编码码点序列y
,sticky搜索方式
Tools
列举了一些工具
其他
什么是正则表达式?普通的语言完全没有规则,正则表达式则是具有一定规则的语言的,即是受到了一定管制的语言,所以叫regular language。regular之上还是formal lanugage,是更形式化的语言。前者是语言加上一些规则,后者是从规则定义出的语言。
RegExp标类的参考文档。
参考:
- https://v8.dev/blog/speeding-up-regular-expressions
- An additional non-backtracking RegExp engine
- KaText中正则的使用示例:https://github.com/KaTeX/KaTeX/blob/main/src/Lexer.js
- lexer.coffee示例:https://coffeescript.org/v1/annotated-source/lexer.html
- JS RegExp, Fast and Slow
(本篇完)