正则表达式最早是由 Ken Thompson 于 1970 年在他改进过的 QED 编辑器里实现的,正则里最简单的元字符 “.” 在当时所匹配的就是除换行符外的任意字符:

"." is a regular expression which matches any character except <nl>.
上面这句话出自 QED 在 1970 年的官方文档,这可能是史上第一份正则文档。
为什么要这么规定?是因为 QED 是以行为单位来编辑文件的,而且行尾的换行符也算在这一行的内容里。比如你想把一段代码中所有的单行注释删掉,在 QED 里可以用下面这句命令:
1,$s#//.*##
如果 “.” 能匹配到换行符,那么换行符也会被删除,会导致这些行和它的下一行合并,这通常都不是我们想要的结果,所以,“.” 在最初发明时被设计成了不能匹配换行符。虽然现在的操作系统上已经没有 QED 命令让我们测试了,但我们还有 VIM,VIM 里的 “.” 也一样不能匹配换行符,因为同样的原因。
不像在 Node 中,读取文件通常是一股脑读完整个文件,Perl 继承了众多 Linux 命令按行读取文件的传统,像这样:
while (<>) {print $_}
_ 的末尾也有换行符,所以 Perl 也就很自然的继承了 QED 的 “.” 不匹配换行符的规定。但 Perl 毕竟是门编程语言,而不是编辑器,它的正则要匹配的对象不单单会是单行文本,还可能是多行文本,因此在它的正则中,“.” 有跨行匹配的需求,因此 Perl 发明了正则的单行模式 /s,即让 “.” 也能匹配换行符。
Perl 中用来打开单行模式的 /s 修饰符的官方描述是 “Treat the string as single line”,这个 “single line” 要这么理解:“.” 在普通模式下只能匹配行内字符,不能跨行;而在单行模式下,Perl 会假装把多行字符串看成一行,把其中的换行符看做是行内字符,所以 “.” 也就能匹配它们了。更形象点说,就是把下面的三行文本
1 2 3
看成 "1\n2\n3\n" 一行文本,单行模式就是这个意思。
但要命的是,因为同样的原因(字符串变量可以包含多行文本),Perl 还发明了 /m 修饰符,即多行模式,官方描述是 “Treat the string as multiple lines”,这个模式 JavaScript 的正则里自古也有,这里这个“多行”的意思是说:^ 和 $ 元字符默认不会匹配一个字符串中间的那些换行符前后的位置,即认为字符串永远只有一行,打开多行模式后就能匹配了。
也就是说,单行模式和多行模式是针对不同的元字符的,刚接触正则的人都会被“单行模式”和“多行模式”这两个看似是相对应的概念,实则毫无关联的名词给搞晕。
后来,Ruby 的作者可能觉得“单行模式”这个正则术语起的不好,特例独行把让 “.” 匹配换行符这一模式称之为“多行模式”,即让 .* 之类的正则能够匹配多行了,所以也完全讲得通,修饰符也用了 /m(Ruby 中默认会开启 Perl 中的“多行模式”,所以 /m 没被占用),这真是雪上加霜,更乱了。
再后来,Python 作者可能也觉得应该避免“单行模式”这个叫法,于是起了个新的名字 “dotall”,也就是让 dot 能匹配所有字符的意思,很好的名字,再后来 Java 也使用了这个名字。
上面回顾了一下历史,解释了下单行模式的由来以及说明了下单行模式这个名字起得不好。V8 最近刚刚实现了一个 stage 3 的 ES 提案 https://github.com/mathiasbynens/es-regexp-dotall-flag,这个提案为 JavaScript 的正则引入了 /s 修饰符和 dotAll 属性,dotAll 属性是学了 Python 和 Java,/s 修饰符是继承了 Perl 的,这里也没必要发明一个新的修饰符比如 /d,只会让事情更复杂。/s 在 JavaScript 的具体效果是让 “.” 能匹配以前不能匹配的四个行终止符:\n(换行)、\r(回车)、\u2028(行分隔符)、\u2029(段落分隔符):
/foo/s.dotAll // true
/^.{4}$/s.test("\n\r\u2028\u2029") // true
其实就是个很简单的东西,但可能一些没有接触过 JavaScript 以外的正则的同学到时候学到这个新的模式后会产生困惑,这里再澄清一下:多行模式控制的是 ^ 和 $ 的表现,单行模式控制的是 “.” 的表现,两者没有直接关系。
然而当初引入单行模式和多行模式这两个易混淆概念的 Perl 语言,已经在 Perl 6 中完全删除了这两个模式:“.” 号默认就匹配换行符,\N 可以匹配换行符除外的任意字符;^ 和 $ 始终匹配字符串的首尾,而新引入了 ^^ 和 $$ 两个元字符来匹配行的首尾。
过去我们常用的单行模式的替代品 [^] 或者 [\s\S] 也不是完全没有用了,比如在一些使用 JavaScript 正则的编辑器里(VS Code、Atom),不太可能给你提供开启单行模式的界面。不过说起编辑器里的正则功能,用 JavaScript 实现的编辑器的正则功能还是太弱了,比如不能在正则自身内部开启某些模式,比如要是在 Sublime(使用 Python 正则)里的话,在正则内部使用 (?s) 就能开启 dotall 模式,比如可以用 (?s)/\*.+?\*/ 匹配到所有的多行注释。
# 正则
# 单行模式
# JS中正则表达式全局匹配模式 /g用法详解
# JS正则获取HTML元素的方法
# php与javascript正则匹配中文的方法分析
# js正则表达式验证密码强度【推荐】
# 一个容易犯错的js手机号码验证正则表达式(推荐)
# javascript 正则表达式分组、断言详解
# 换行符
# 的是
# 就能
# 修饰符
# 这两个
# 用了
# 也有
# 可以用
# 器里
# 编辑器
# 继承了
# 跨行
# 的人
# 这一
# 是个
# 文档
# 是在
# 分隔符
# 很好
# 是因为
相关文章:
c++ stringstream用法详解_c++字符串与数字转换利器
如何在万网主机上快速搭建网站?
北京制作网站的公司,北京铁路集团官方网站?
小自动建站系统:AI智能生成+拖拽模板,多端适配一键搭建
如何在阿里云域名上完成建站全流程?
MySQL查询结果复制到新表的方法(更新、插入)
安云自助建站系统如何快速提升SEO排名?
定制建站价位费用解析与套餐推荐全攻略
如何通过山东自助建站平台快速注册域名?
红河网站制作公司,红河事业单位身份证如何上传?
网站制作公司排行榜,四大门户网站排名?
济南专业网站制作公司,济南信息工程学校怎么样?
家庭建站与云服务器建站,如何选择更优?
教学论文网站制作软件有哪些,写论文用什么软件
?
网站app免费制作软件,能免费看各大网站视频的手机app?
北京网站制作网页,网站升级改版需要多久?
利用JavaScript实现拖拽改变元素大小
制作网站建设的公司有哪些,网站建设比较好的公司都有哪些?
如何在阿里云虚拟主机上快速搭建个人网站?
已有域名如何免费搭建网站?
如何配置IIS站点权限与局域网访问?
c# 在高并发下使用反射发射(Reflection.Emit)的性能
建站之星代理如何优化在线客服效率?
昆明网站制作哪家好,昆明公租房申请网上登录入口?
深圳企业网站制作设计,在深圳如何网上全流程注册公司?
定制建站方案优化指南:企业官网开发与建站费用解析
沈阳制作网站公司排名,沈阳装饰协会官方网站?
广州营销型建站服务商推荐:技术优势与SEO优化解析
公司网站制作费用多少,为公司建立一个网站需要哪些费用?
猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?
交易网站制作流程,我想开通一个网站,注册一个交易网址,需要那些手续?
如何快速选择适合个人网站的云服务器配置?
rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted
,在苏州找工作,上哪个网站比较好?
制作公司内部网站有哪些,内网如何建网站?
建站之星如何快速更换网站模板?
太平洋网站制作公司,网络用语太平洋是什么意思?
Thinkphp 中 distinct 的用法解析
教育培训网站制作流程,请问edu教育网站的域名怎么申请?
建站主机与服务器功能差异如何区分?
Bpmn 2.0的XML文件怎么画流程图
如何确保FTP站点访问权限与数据传输安全?
北京专业网站制作设计师招聘,北京白云观官方网站?
jQuery 常见小例汇总
英语简历制作免费网站推荐,如何将简历翻译成英文?
建站主机是否属于云主机类型?
制作网站的基本流程,设计网站的软件是什么?
历史网站制作软件,华为如何找回被删除的网站?
建站之星后台密码如何安全设置与找回?
建站三合一如何选?哪家性价比更高?
*请认真填写需求信息,我们会在24小时内与您取得联系。