- 文档/教程
- 前端
【免费下载链接】en.javascript.info
Modern JavaScript Tutorial
导读
在处理多行文本(如日志、配置文件、Markdown 正文)时,正则表达式的行首、行尾匹配是最常见也最容易出错的需求。本篇文章聚焦 Modern JavaScript Tutorial 中「正则表达式多行模式(Multiline mode)」这一章节,系统讲解m标志如何改变锚点^与$的匹配行为:默认情况下它们只匹配整个字符串的开头与结尾,而开启多行模式后则会匹配每一行的开头与结尾。读完本文,你将彻底理解^、$与换行符\n的本质区别,并能用它们准确提取多行文本中每行的关键内容。
一、什么是多行模式:标志m
JavaScript 的正则表达式支持 6 个标志(flags),分别是i(忽略大小写)、g(全局匹配)、m(多行模式)、s(dotall,让.匹配换行符)、u(完整 Unicode 支持)、y(sticky 粘性匹配),详见 正则表达式入门章节。
其中,标志m(multiline)的职责非常单一:
多行模式只影响锚点
^与$的行为。
在默认(非多行)模式下,^只在整个字符串的开头匹配,$只在整个字符串的结尾匹配;而在多行模式下,它们不仅匹配文本整体首尾,还会在每一行的开头 / 结尾处匹配。
关于^与$在默认模式下的基础行为,可以回看本系列前一篇 锚点:字符串开头 ^ 与结尾 $,其中强调了一个关键性质:锚点不是字符,而是"零宽度"(zero width)的测试——它们不消费任何字符,只是让正则引擎在当前位置检查"是否处于文本开头/结尾"这一条件。理解这一点,对理解多行模式至关重要。
二、行首匹配:^在多行模式下
2.1 开启m后,每行开头都能命中
假设我们有一段三行文本,记录了三名选手的名次:
let str = `1st place: Winnie 2nd place: Piglet 3rd place: Eeyore`; console.log( str.match(/^\d/gm) ); // 1, 2, 3模式pattern:/^\d/gm由三部分组成:^要求当前位置是"行首",\d要求紧接着是一个数字,g表示查找全部匹配,m开启多行模式。最终结果得到1, 2, 3——三行的第一个数字都被捕获了。
2.2 关闭m后,只有整个文本开头的数字能命中
同样的文本、同样的^与\d,只是去掉m标志:
let str = `1st place: Winnie 2nd place: Piglet 3rd place: Eeyore`; console.log( str.match(/^\d/g) ); // 1结果只剩一个1。原因正如文档所强调的:默认情况下^只在文本开头匹配,而文本开头只有一个,所以只取到第一个数字。
2.3 "行首"的精确定义
这里有一个容易忽略的细节,文档用专门的提示框给出正式定义:
"行首"(start of a line)正式含义是"紧跟换行符之后":多行模式下,
^测试会在所有前面紧邻换行符\n的位置匹配,当然也包括文本的最开头。
换句话说,^在m模式下匹配的位置集合是:{文本开头} ∪ {每个 \n 之后的紧邻位置}。这个定义决定了多行模式下"行"的边界就是\n。
三、行尾匹配:$在多行模式下
$的行为与^完全对称。
3.1 开启m后,每行结尾的数字都能命中
把上一节的例子改造成"查找每一行最后一个数字":
let str = `Winnie: 1 Piglet: 2 Eeyore: 3`; console.log( str.match(/\d$/gm) ); // 1,2,3模式pattern:\d$要求"一个数字紧邻行尾",配合g与m,得到三行各自的末尾数字1, 2, 3。
3.2 关闭m后,只有整个文本的最后一个数字命中
如果去掉m:
let str = `Winnie: 1 Piglet: 2 Eeyore: 3`; console.log( str.match(/\d$/g) ); // 3由于$默认只匹配整个文本的结尾,而整个文本以3收尾,所以只找到最后一个数字。
3.3 "行尾"的精确定义
与"行首"对应,文档同样给出正式定义:
"行尾"(end of a line)正式含义是"紧邻换行符之前":多行模式下,
$测试会在所有后面紧邻换行符\n的位置匹配,当然也包括文本的最末尾。
也就是说,$在m模式下匹配的位置集合是:{文本末尾} ∪ {每个 \n 之前的紧邻位置}。注意3之后没有换行符,但它处于文本末尾,因此依然满足$的匹配条件。
四、用\n代替^ $行吗?区别在哪里
既然多行模式让^、$可以定位行首行尾,那为什么不直接匹配换行符\n呢?文档专门用一个小节回答了这个问题。
4.1 用\n匹配的后果
把上一节的pattern:\d$改成pattern:\d\n:
let str = `Winnie: 1 Piglet: 2 Eeyore: 3`; console.log( str.match(/\d\n/g) ); // 1\n,2\n结果从 3 个匹配变成了 2 个。原因有两点:
- 最后一行没有换行符:
Eeyore: 3之后是文本末尾而不是\n,所以3\n无法匹配。而$锚点可以匹配文本末尾,因此3在\d$(带m)中能命中。 \n是字符,会进入匹配结果:\n是实实在在的字符,因此每次匹配结果中都包含换行符本身(输出为1\n,2\n)。而^、$是零宽度的测试,它们只检查位置条件,不会把任何字符带入匹配结果。
4.2 选择依据
文档给出了非常清晰的取舍结论,可以直接当作决策准则:
- 当你需要把换行符本身作为结果的一部分(例如按行切分后要保留行结束符)时,用
\n; - 当你只是需要找到位于某行开头或结尾的内容(换行符不应该出现在匹配结果里)时,用带
m标志的锚点^/$。
用一句话概括:锚点管"位置",\n管"字符"。锚点只做条件测试、零宽度、不消费字符;而\n是一个真实的字符,参与匹配并出现在结果中。这与前一篇 锚点章节 强调的"锚点零宽度"特性一脉相承。
五、实战延伸:多行模式与锚点的典型配合
在 Modern JavaScript Tutorial 的正则表达式系列中,多行模式常与其他锚点类特性配合使用,这里给出几个基于仓库既有内容的实战视角。
5.1 多行模式 + 全字符串校验的边界
在 锚点章节的练习题 中,^...$组合被用来校验整个字符串是否完全符合某种格式(例如时间12:34)。练习的解答特意强调:^与$是测试而非字符,即使对空字符串"",^与$也能同时命中。这与多行模式直接相关:一旦加上m,^...$就退化为"逐行校验",此时每一行都会被独立要求满足完整格式——这是实现"逐行格式校验"的高效手段。
5.2 多行模式 + 单词边界\b
另一类与行首行尾高度相关的锚点是单词边界\b(详见 单词边界章节)。\b同样是零宽度测试,它检查位置两侧是否一边是单词字符\w、一边不是。实际处理多行文本时,常把^、$与\b组合:^\b\d+\b$(带m)可以精确匹配"整行恰好是一个独立的数字"。这类模式在日志解析、配置文件校验、命令行输出处理中非常实用。
5.3 提取结果的注意事项:match与g标志
本文所有示例都依赖str.match(regexp)配合g标志返回全部匹配数组;若没有g,match只返回第一个匹配;若没有任何匹配,match返回null而非空数组。完整的match/matchAll/replace/exec行为可查阅本系列 正则方法与字符串方法,那里还覆盖了lastIndex与全局正则复用的陷阱——这些细节在真实项目中排查"为什么只匹配到第一行"时尤为重要。
六、小结
| 场景 | 模式 | 匹配结果 |
|---|---|---|
| 每行开头的数字 | /^\d/gm | 每行第一个数字(如1, 2, 3) |
| 每行结尾的数字 | /\d$/gm | 每行最后一个数字(如1,2,3) |
| 数字 + 换行符本身 | /\d\n/g | 仅非末行命中,且结果含\n |
| 整个文本开头的数字 | /^\d/g | 仅第一个数字 |
| 整个文本结尾的数字 | /\d$/g | 仅最后一个数字 |
核心要点回顾:
- 标志
m只改变^与$,对.、\d、\b等其他语法没有影响; - 多行模式下:
^匹配"文本开头 + 每个\n之后",$匹配"文本末尾 + 每个\n之前"; - 锚点是零宽度测试:不消费字符、不进入匹配结果,只检查位置条件;
\n是真实字符:需要换行符进入结果时用它,需要定位行首行尾时用锚点。
以上内容整理自 9-regular-expressions/05-regexp-multiline-mode/article.md,并结合同系列 锚点章节、正则表达式入门章节 与 正则方法章节 进行了扩展讲解。建议在阅读本系列时按"入门 → 锚点 → 多行模式 → 单词边界 → 正则方法"的顺序循序渐进,掌握正则表达式的完整能力。
- 文档/教程
- 前端
【免费下载链接】en.javascript.info
Modern JavaScript Tutorial
相关推荐
JavaScript正则表达式教程:多行模式(m标志)详解
JavaScript正则表达式教程:多行模式 m标志 详解 多行模式简介 在JavaScript正则表达式中, m 标志用于启用多行模式 multiline m
Tidal-HiFi API全解析:构建属于你的音乐控制应用
Tidal HiFi API全解析:构建属于你的音乐控制应用 Tidal HiFi是一款基于Electron构建的音乐播放应用,它将Tidal的网页版体验与Wi
JavaScript正则表达式中的锚点:^和$详解
JavaScript正则表达式中的锚点:^和$详解 正则表达式是JavaScript中处理字符串的强大工具,而锚点 anchors 则是正则表达式中非常重要的概
文档/教程前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考