小览 ES6-ES2019 中正则表达式的新发展
栏目: JavaScript · 发布时间: 6年前
内容简介:在此前的本文尝试走马观花,一瞥这些特性,看能否籍此简化我们的开发。
在此前的 《JS正则表达式--从入门到精分》 一文中,曾经较完整的介绍过 Javascript 中正则表达式的用法。而从 ES6(ES2015) 开始,借助 Babel 等标志性的工具,JS 的发展似乎也不想重蹈 Flash 时代的无所作为,走上了每年一个小版本的快车道;在此过程中,正则表达式也陆续演化出一些新的特性。
本文尝试走马观花,一瞥这些特性,看能否籍此简化我们的开发。
ECMAScript 和 TC39
虽然可能是大家普遍了解的事情,但这些称呼反复出现,可能还是需要稍微解释一下先。
ECMA 指的是 “欧洲计算机制造商协会”(European Computer Manufacturers Association);现在也称为 “ECMA 国际”(ECMA International),定位为一家国际性会员制度的信息和电信标准组织。
1996 年 11 月,JavaScript 的创造者 Netscape 公司,决定将 JavaScript 提交给 ECMA,希望这种语言能够成为国际标准。次年,ECMA 发布 262 号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的标准,并将这种语言称为 ECMAScript (简称 ES)。
此后该标准应用广泛,JavaScript、JScript、ActionScript 等都算是 ECMA-262 标准的实现和扩展。
从 1997 年至 2009 年,陆续发布了 ES1 ~ ES5;其中 ES4 其实是偏向于 Adobe 的 ActionScript 风格的实践设计的,但最终也随着 Flash 被市场上其他厂商封杀,以改动过大为名不了了之,但其中一些特性被后来的 ES6 继承。
2015年,可以说迄今最重要的一个版本 ES6,也就是 ES2015(ES6 的第一个版本) 发布。由各个主流浏览器厂商的代表组成 ECMA 第 39 号技术专家委员会(Technical Committee 39,简称 TC39),负责制订新的 ECMAScript 标准。
新的语法从提案到变成正式标准,需要经历五个阶段。每个阶段的变动都需要由 TC39 委员会批准:
-
Stage 0 - Strawman(展示阶段)
-
Stage 1 - Proposal(征求意见阶段)
-
Stage 2 - Draft(草案阶段)
-
Stage 3 - Candidate(候选人阶段)
-
Stage 4 - Finished(定案阶段)
以上这几个也就是我们之前使用 Babel 转译 工具 时会引入 babel-preset-stage-0
等预置方案的原由,当然随着 Babel 7 的发布,这些方案都被统一到了 @babel/preset-env
中。
ES6 中的正则表达式特性
以下特性首次在 ES6 中出现:
-
“粘性”修饰符
/y
-
unicode 修饰符
/u
-
正则表达式对象上的新属性
flags
-
用构造函数
RegExp()
拷贝正则表达式
“粘性”修饰符 /y
修饰符 /y
只将正则表达式的每个匹配锚定到前一个匹配的末尾
简单的说,这主要与正则表达式对象上的 lastIndex
属性有关 -- 其与 /g
或 /y
的搭配,会产生不同的效果。
在不设置修饰符,或只设置了 /g
修饰符的情况下,只要目标字符串(或上一次匹配的剩余部分)中存在匹配就可以。
而 /y
修饰符则告知正则表达式,只能不偏不倚的从字符串的 lastIndex
那个位置去匹配,这也就是“粘性、粘连”的涵义。
以 exec()
的使用为例:
当然,一般情况下 -- 比如第一次运行匹配,或不特别设置 lastIndex
时, /y
的功效大抵和 ^
起始匹配符相同,因为此时 lastIndex
为 0
:
需要注意的是,如果同时设置了 /g
和 /y
,则只有 /y
会生效。
sticky
属性
与 /y
修饰符相配套,ES6 的正则表达式对象多了 sticky
属性,表示是否设置了 /y
修饰符:
unicode 修饰符 /u
这里简单解释一下 Unicode,其目标是为世界上每一个字符提供唯一标识符,该唯一标识符可称为 码点(code point) 或 字符编码(character encode)。
在 ES6 之前, JS 的字符串以 16 位字符编码(UTF-16)为基础。每个 16 位序列(相当于2个字节)是一个 编码单元(code unit,可简称为码元) ,用于表示一个字符。字符串所有的属性与方法(如 length
属性与 charAt()
方法等)都是基于这样 16 位的序列。
本来 JS 允许采用 \uxxxx
形式表示一个常用的 unicode 字符,其中的 4 个十六进制数字表示字符的 unicode 码点:
同时,这种表示法只能表示码点局限于 0x0000
~ 0xFFFF
之间的字符。超出这个范围的字符,必须用两个码元连接的形式(称为 surrogate-pairs,代理对)表示一个码点:
这就导致了一个问题,对于一些超出 16 位 0xFFFF
的 unicode 字符,传统的方法就会出错;比如直接在 \u20BB7
,JS 会理解成 \u20BB
+ 7
;所以会显示成一个特殊字符,后面跟着一个 7。
对此 ES6 做出了改进,将 unicode 编码放入大括号(这种语法称为 unicode 码点转义符),就可以正确解读字符了:
同样的例子:
此中的转换对应关系,这篇文章( https://blog.csdn.net/hherima/article/details/38961575 )做了比较清楚的探寻,感兴趣的话可以结合文末的资料进行研究;本文不展开掰哧,能体会示例即可。
书归正传,在 ES6 的正则中:
修饰符 /u
将正则表达式切换为特殊的 Unicode
模式
在 Unicode 模式下,既可以使用新的大括号 unicode 编码点转义符表示范围更大的字符,也可以继续使用 UTF-16 码元。该模式具有如下特征:
-
“单独代理”(lone surrogates)特性:
-
可以将码点放入正则的字符类中:
-
点操作符匹配码点,而非码元
-
数量描述符也同样匹配到码点
正则表达式对象上的新属性 flags
新增的 flags
属性,会返回正则表达式的修饰符
用 RegExp()
拷贝正则表达式
正则表达式构造函数的传统签名是 newRegExp(pattern:string,flags='')
,比如:
ES6中,新增的用法是 newRegExp(regex:RegExp,flags=regex.flags)
:
这就提供了一种拷贝已有正则表达式,或更改其修饰符的方法。
ES2018/ES2019 中的新特性
在 ES2018 - ES2019 中,又增加了一些特性:
-
命名捕获组
-
反向引用
-
反向断言
-
unicode 属性转义
-
dotAll 修饰符
/s
命名捕获组
此前的正则表达式操作中,采用的是“编号捕获组”(Numbered capture groups)匹配字符串并将之分组,比如:
这种方式无论从易用性还是复杂度方面都不太理想,尤其当字段过多、存在嵌套等情况时;如果改动了正则表达式还容易忘记同步改变分散在各处的编号。
ES6 带来的“命名捕获组”(Named capture groups),则可以通过名称来识别捕获的分组
-
其格式如
(?<year>[0-9]{4})
-
通过捕获结果中的
groups.year
属性取出 -
任何匹配失败的命名组都将返回 undefined
这还为 replace()
方法提供了额外的便利,注意其语法:
反向引用(Backreferences)
正则表达式中的 \k<name>
表示这样的意思:根据前一次匹配到的命名捕获组中的名称,匹配相应的字符串,比如:
这种称为 反向引用 的语法,对于编号捕获组同样适用:
两掺儿的,也没问题:
反向断言(lookbehind assertions)
根据之前文章的介绍,JS 中已经支持了“正向断言”(Lookahead assertions),或称为正向查找。
-
x(?=y)
匹配'x'仅仅当'x'后面跟着'y'。称为正向肯定查找 -
x(?!y)
匹配'x'仅仅当'x'后面不跟着'y'。称为正向否定查找
ES2018 引入了反向断言(lookbehind assertions),与正向断言的工作方式相同,只是方向相反
同样也分为两种子类型:
-
y(?<=x)
匹配'x'仅仅当'x'前面挨着'y'。称为 反向肯定查找
-
y(?<!x)
匹配'x'仅仅当'x'前面不挨着'y'。称为 反向否定查找
unicode 属性转义
在 ES6 的 /u
修饰符基础上,ES2018 添加了 "unicode 属性转义"(Unicode property escapes) -- 形式为 \p{...}
及 \P{...}
,分别表示“包含”和“不包含”
从目的和形式上这很类似于用 \s
来匹配空格等 whitespace,而 \p{}
和 \P{}
花括号中的部分称为 "unicode 字符属性" (Unicode character properties),让正则表达式有了更好的可读性。
所谓“unicode 字符属性”,是指在 Unicode 标准中,每个字符都有用于描述其性质的元数据: properties
,比如:
-
Name
: 一个唯一的名称,由大写字母、数字、连字符、空格组成,如: -
A
: Name = LATIN CAPITAL LETTER A -
:grinning:
: Name = GRINNING FACE -
General_Category
: 分类的字符,如: -
x
: General Category = Lowercase Letter -
$
: General Category = Currency Symbol -
White_Space
: 用于标记不可见的空格、制表符、换行等字符,如: -
\t
: White Space = True -
π
: White Space = False -
Age
: Unicode 标准的版本号,如: -
€
: Age = 2.1 -
Block
: 码点的一个连续范围,不会重复,命名也是唯一的,如: -
S
: Block = Basic_Latin (range U+0000..U+007F) -
:grinning:
: Block = Emoticons (range U+1F600..U+1F64F) -
Script
: 一个字符集合,用于一个或多个书写系统 -
α
: Script = Greek -
Д
: Script = Cyrillic -
某些 script 支持多个书写系统,比如 Latin script 支持 English, French, German, Latin 等
-
某些语言可以用由多种 script 支持的多种替代书写系统书写。例如,土耳其语在 20 世纪早期转变为 Latin script 之前就使用了 Arabic script。
-
举例来说:
另外几个例子:
dotAll 修饰符 /s
我们通常会在很多正则表达式中见到一种 [\s\S]
的匹配小技巧,这种看似多余的写法其实是为了弥补 .
标记无法在多行的情况下实现正确匹配的缺憾。
修饰符 /s
解决了这个问题,所以也称为 dotAll 修饰符。
关于 .
标记,顺便一提的是:
参考资料:
-
《JS正则表达式--从入门到精分》 https://mp.weixin.qq.com/s?__biz=MzI0MDYzOTEyOA==&mid=2247483694&idx=1&sn=e79f23c86e48b6a85d30d612e1d5a2eb&chksm=e9168cd9de6105cf647ceabac1a2ee737d0867e7b3cdab243e3cd889b295e3ab9666820ad02d
-
http://exploringjs.com/es6/ch regexp.html#sec regexp
-
http://exploringjs.com/es2018-es2019/toc.html
-
http://www.cnblogs.com/dandelion-drq/p/js regular expression_note.html
-
http://www.appui.org/2496.html
-
https://stackoverflow.com/questions/4542304/what-does-regex-flag-y-do
-
http://www.cnblogs.com/detanx/p/es6zz.html
-
http://www.cnblogs.com/xiaohuochai/p/7230328.html
-
https://www.princeton.edu/~mlovett/reference/Regular-Expressions.pdf
-
https://unicodebook.readthedocs.io/unicode_encodings.html#utf-16-c
-
https://docs.microsoft.com/zh-cn/previous-versions/8k5611at(v=vs.110)
-
https://blog.csdn.net/hherima/article/details/38961575
-
https://arui.tech/es2018-new-features/#UnicodeUnicode property escapes
-
https://github.com/tc39/proposal-regexp-unicode-property-escapes
-
http://caibaojian.com/es6/
-
https://zhuanlan.zhihu.com/p/27762556
-
https://babeljs.io/docs/en/babel-preset-env
--End--
搜索 fewelife 关注公众号
转载请注明出处
以上所述就是小编给大家介绍的《小览 ES6-ES2019 中正则表达式的新发展》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
莱昂氏UNIX源代码分析
(澳)John Lions / 尤晋元 / 机械工业出版社 / 2000-7-1 / 49.00
本书由上、下两篇组成。上篇为UNIX版本6的源代码,下篇是莱昂先生对UNIX操作系统版本6源代码的详细分析。本书语言简洁、透彻,曾作为未公开出版物广泛流传了二十多年,是一部杰出经典之作。本书适合UNIX操作系统编程人员、大专院校师生学习参考使用。一起来看看 《莱昂氏UNIX源代码分析》 这本书的介绍吧!