JavaScript的正则也有单行模式了

网络编程 2025-03-30 03:57www.168986.cn编程入门

这篇文章主要了JavaScript正则表达式中的单行模式,让我们一同回顾历史,深入理解这个模式的由来,以及在不同编程语言中的实现方式。

正则表达式的起源可以追溯到1970年,由Ken Thompson在QED编辑器中首次实现。最初的正则表达式最简单的元字符"."在设计时,其匹配规则是不包含换行符的任意字符。这是因为QED编辑器是以行为单位编辑文件的,行尾的换行符也被视为该行内容的一部分。例如,在QED编辑器中删除单行注释的命令中,"."若匹配到换行符,会导致不期望的行合并现象。"."在最初的设计中是不能匹配换行符的。这种规则也被后续的编辑器如VIM所继承。

不同于Node.js一次性读取整个文件的方式,Perl等语言继承了Linux命令按行读取文件的传统。Perl中的"."也不匹配换行符。但Perl作为编程语言,其正则表达式的应用范围更广,不仅包括单行文本,还包括多行文本。为了满足跨行匹配的需求,Perl引入了正则的单行模式/s,使得"."也能匹配换行符。这个模式的意思是将多行文本视为单行,把其中的换行符看作普通字符。

由于字符串变量可以包含多行文本,Perl还引入了多行模式/m。这个模式的意思是,^和$元字符默认不会匹配字符串中间的换行符前后的位置,只有在多行模式下才能匹配。这给人一种困扰,因为单行模式和多行模式看似相对应,实则毫无关联。

后来,Ruby的作者可能对“单行模式”这个术语有所不满,于是将让"."匹配换行符的模式称为“多行模式”。Python则使用了“dotall”这个名字,意思是让"."能匹配所有字符。Java也采用了这个名字。

最近,V8引擎实现了ES提案中的/s修饰符和dotAll属性。其中,dotAll属性是学习了Python和Java的命名方式,而/s修饰符则是继承了Perl的命名方式。在这个提案中,没有必要发明新的修饰符如/d,只会增加复杂性。

单行模式在正则表达式的发展历程中经历了许多演变和命名方式的改变。理解这些历史背景和差异有助于我们更好地使用JavaScript中的正则表达式,并避免在使用中出现混淆。在JavaScript的世界中,正则表达式的“.”(点号)拥有了新的能力,它现在可以匹配那些曾经无法触及的四个特殊字符:换行()、回车(\r)、行分隔符(\u2028)和段落分隔符(\u2029)。这种改变赋予了“.”在多行文本中的更强大的匹配能力。

当你运行`/foo/s.dotAll`这样的代码时,返回`true`,说明正则表达式的点号现在能够匹配包括换行在内的所有字符。同样,当你使用`/^.{4}$/s.test("\r\u2028\u2029")`时,也会返回`true`,这进一步验证了点号在单行模式下的强大匹配能力。

尽管这是一个相对简单的概念,但对于没有接触过JavaScript以外的正则表达式的同学来说,可能会产生一些困惑。这里需要澄清的是,多行模式主要影响的是`^`和`$`的表现,它们分别代表字符串的开头和结尾,而单行模式则控制的是“.”的表现。这两者之间并没有直接的联系。

值得一提的是,当初引入单行模式和多行模式这两个易混淆概念的Perl语言,已经在Perl 6中彻底改变了这一设定。“.”号在Perl 6中默认就可以匹配换行符,而`\N`则可以匹配除换行符以外的任意字符。`^`和`$`始终匹配字符串的首尾,而新引入了`^^`和`$$`两个元字符来匹配行的首尾。

在过去,我们常用的单行模式的替代品,如`[^]`或者`[\s\S]`在某些使用JavaScript正则的编辑器(如VS Code、Atom)中仍然有其用处。但由于JavaScript实现的编辑器的正则功能相对较弱,我们无法在正则内部直接开启某些模式。比如在Sublime(使用Python正则)中,我们可以使用`(?s)`来开启dotall模式,从而实现更复杂的多行匹配。例如,使用`(?s)/\.+?\/`可以匹配到所有的多行注释。这种灵活性在JavaScript的编辑器中是无法实现的。

通过 `cambrian.render('body')` ,我们可以将上述的内容以一种生动的、丰富的方式呈现给读者。

上一篇:js鼠标经过tab选项卡时实现切换延迟 下一篇:没有了

Copyright © 2016-2025 www.168986.cn 狼蚁网络 版权所有 Power by