讲解
标志位(flags)写在正则末尾,改变整个模式的匹配规则。JavaScript 有六个:i(ignoreCase)忽略大小写;g(global)找全部匹配而不是第一个;m(multiline)让 ^ $ 匹配每行首尾;s(dotAll)让点号也能匹配换行;u(unicode)按 Unicode 码点处理,emoji 等字符不再被拆成半个;y(sticky)粘连模式,要求匹配必须从 lastIndex 指定的位置开始。写法是 /pattern/flags,可以组合,比如 /\d+/gi。
g 是使用频率最高、坑也最多的标志。不加 g 时 match 返回第一个匹配及捕获组;加了 g 返回所有匹配的数组、但捕获组信息丢失——要「全部匹配 + 捕获组」得用 matchAll。另外带 g 的正则对象是有状态的(记住 lastIndex),这是 JavaScript 章节要细讲的著名陷阱。
s 和 m 解决两类「跨行」问题:s 管的是 . 能不能跨过换行(提取多行内容时用),m 管的是 ^$ 锚在哪(逐行处理时用)。u 标志让正则按码点而不是 UTF-16 码元工作,处理 emoji 时必须加;它还顺手开启了更严格的语法检查,一些模糊的转义在 u 模式下会直接报错,这其实是好事。y 常用于词法分析器逐段扫描,日常用得少但概念值得知道。
示例
// i:忽略大小写
console.assert(/^cat$/i.test('CAT'));
console.assert(/^cat$/i.test('Cat'));
// g:找全部而不是第一个
console.assert('a1b22c333'.match(/\d+/g).join(',') === '1,22,333');
console.assert('a1b22c333'.match(/\d+/)[0] === '1'); // 不加 g 只取第一个
console.assert('a1b22c333'.match(/\d+/g).length === 3);
s 与 m:一个管点号跨行,一个管锚点逐行。
const html = '<div>\n 内容\n</div>';
// s(dotAll):让点号匹配换行
console.assert(/<div>.*<\/div>/.test(html) === false); // 不加 s:点号跨不了行
console.assert(/<div>.*<\/div>/s.test(html) === true);
// m(multiline):^ $ 匹配每一行的首尾
console.assert('one\ntwo\nthree'.match(/^\w+$/gm).join(',') === 'one,two,three');
u 与 y:
// 不加 u:点号按 UTF-16 码元匹配,一个 emoji 有两个码元
console.assert(/^.$/.test('👍') === false);
// 加 u:点号按码点匹配,emoji 是一个完整字符
console.assert(/^.$/u.test('👍') === true);
console.assert(/👍/u.test('好 👍 耶'));
// y(sticky):必须从 lastIndex 位置开始匹配,不许往后找
const lexer = /\d+/y;
lexer.lastIndex = 0;
console.assert(lexer.exec('123abc')[0] === '123'); // 从 0 开始正好是数字
lexer.lastIndex = 3;
console.assert(lexer.exec('123abc') === null); // 位置 3 是字母,粘连模式不匹配
console.assert(/\d+/.exec('abc123')[0] === '123'); // 普通模式会往后找到 123
常见坑
- 带 g 的正则对象反复 test/exec:lastIndex 会移动,同一个对象两次 test 同样输入结果可能不同。这是 JavaScript 正则最著名的坑,下一章有完整示例和对策。
- 以为 s 是默认行为:不是。点号默认不跨行,多行内容提取记得加 s,或者改用 [\s\S] 这类全字符类。
- 混淆 m 和 s:m 影响 ^$ 锚的位置,s 影响 . 的覆盖面,互不相干,按需取用。
- 加 g 后还用 match 取捕获组:/g 模式下 match 返回的数组里没有组信息,需要捕获组请用 [...str.matchAll(/re/g)]。
小结
i g m s u y 六个标志分别控制大小写、全局、多行锚点、点号跨行、Unicode 码点与粘连匹配;g 的 lastIndex 状态是最常见的坑。下一节进入实战:常用模式集锦。