跳到主要内容

锚点与边界

^ 与 $ 锚点匹配什么位置?​

  • 名字: 二者称为锚点 (anchor);
  • ^: 匹配文本开头;
  • $: 匹配文本结尾;
  • 宽度: 零宽, 不消费字符, 只让引擎校验"是否在指定位置";
  • 用途: 单端判断开头/结尾, 或首尾配对做整串格式校验;
/^Mary/.test("Mary had a little lamb"); // true
/snow$/.test("its fleece was white as snow"); // true

/^\d\d:\d\d$/.test("12:34"); // true
/^\d\d:\d\d$/.test("12:345"); // false
  • 整串校验: ^...$ 要求模式紧贴文本首尾, 多一个字符即不匹配;
  • 选择: 仅判断前缀/后缀时, startsWith/endsWith 更直接, 正则留给更复杂的条件;

m 标志如何改变 ^ 与 $ 的行为?​

  • 影响面: m 只改变 ^ 与 $, 不改其它符号;
  • 默认: ^ 只在文本开头成立, $ 只在文本结尾成立;
  • 多行模式: ^ 在任一行开头成立, $ 在任一行结尾成立;
  • 行的定义: "行首"即紧跟在换行符 \n 之后的位置, "行尾"即紧邻 \n 之前的位置, 再加上文本首尾;
const str = `1st place: Winnie
2nd place: Piglet
3rd place: Eeyore`;

str.match(/^\d/gm); // 1, 2, 3
str.match(/^\d/g); // 1

`Winnie: 1\nPiglet: 2\nEeyore: 3`.match(/\d$/gm); // 1, 2, 3

用 \n 代替 $ 有什么区别?​

  • 差别一: \n 是字符, 会进入匹配结果; 锚点是零宽校验, 不占结果;
  • 差别二: 最后一行末尾没有 \n, 因此 \n 版本少一个匹配;
const str = `Winnie: 1
Piglet: 2
Eeyore: 3`;

str.match(/\d\n/g); // 1\n, 2\n (2 个)
str.match(/\d$/gm); // 1, 2, 3 (3 个)
  • 选型: 结果需要包含换行符时用 \n; 只想定位行首/行尾内容时用锚点;

\b 词边界判定哪些位置?​

  • 性质: 与 ^/$ 同类, 是零宽校验;
  • 判定规则: 一侧是 \w, 另一侧不是 \w 时, 该位置即为词边界;
  • 成立位置:
    • 文本开头, 且首字符是 \w;
    • 两个字符之间, 一为 \w 一非 \w;
    • 文本结尾, 且末字符是 \w;
"Hello, Java!".match(/\bJava\b/); // Java
"Hello, JavaScript!".match(/\bJava\b/); // null
"Hello, Java!".match(/\bHello\b/); // Hello
"Hello, Java!".match(/\bHell\b/); // null: l 之后不是边界
"Hello, Java!".match(/\bJava!\b/); // null: ! 之后不是 \w
  • 也可用于数字: \b\d\d\b 找由非 \w 包围的两位数;
"1 23 456 78".match(/\b\d\d\b/g); // 23, 78
"12,34,56".match(/\b\d\d\b/g); // 12, 34, 56
  • 局限: \b 依赖 \w 的定义 (仅拉丁字母、数字、下划线), 对西里尔文、汉字等无效, 详见 正则基础与字符类;
  • 与量词组合: 可用它把模式锁定为独立词, 详见 量词与贪婪模式;