锚点与单词边界
前面学的字符类、量词都是匹配字符的,这一章讲一类特殊的元素——它们匹配的是位置,不消耗任何字符,称为零宽断言(zero-width assertion)。最常用的就是开头锚点、结尾锚点、单词边界。
开头锚点与结尾锚点
脱字符匹配字符串的开头,美元符号匹配结尾。它们不消耗字符——匹配成功后,引擎的当前位置不前进。这一点很关键,后面会和环视一起深入。
// 锚点(anchor):不消耗字符,只匹配"位置"
^ 字符串开头(或多行模式下每行开头)
$ 字符串结尾(或多行模式下每行结尾)
\b 单词边界(word boundary)
\B 非单词边界(\b 的反义)
\A 字符串绝对开头(不受多行影响,部分语言支持)
\Z 字符串绝对结尾(部分语言支持)
// 关键:锚点"零宽"——匹配成功后位置不前进
/^hello/.test("hello world"); // true (开头必须是 hello)
/^hello/.test("say hello"); // false (开头不是 hello)
/world$/.test("hello world"); // true (结尾必须是 world)
/world$/.test("world peace"); // false (结尾不是 world)
// 同时锚定两端:整个字符串必须完全匹配
/^\d+$/.test("12345"); // true
/^\d+$/.test("12a45"); // false (中间有字母)
/^\d+$/.test(" 12345 "); // false (两端有空格)最常见用法是把模式两端都锚定,这样要求"整个字符串完全匹配",而不是"在任意位置搜到"。表单校验几乎都是这种用法——手机号、邮编、密码,都必须整段匹配才算合法。
单词边界
单词边界是"单词字符"(字母、数字、下划线)和"非单词字符"之间的位置。它解决了"想匹配独立单词,但不想被包含在更长单词里"这个高频需求。
// 单词边界(word boundary)
// \b 匹配"单词字符"和"非单词字符"之间的位置
// 单词字符 = [a-zA-Z0-9_]
/cat/.test("catalog"); // true (cat 在 catalog 里也能匹配)
/\bcat\b/.test("catalog"); // false (cat 前后必须有边界)
/\bcat\b/.test("a cat here"); // true (cat 是独立单词)
/\bcat\b/.test("my-cat!"); // true (连字符和感叹号都是边界)
// 常见用途 1:精确匹配某个单词(不被包含在更长单词里)
/\berror\b/g // 只匹配独立单词 error,不匹配 errors 或 errorLog
// 常见用途 2:重复单词检测
/\b(\w+)\s+\1\b/ // 匹配 "the the" "is is" 这种重复
// \B 是 \b 的反义:非单词边界
/\Bcat/.test("concat"); // true (cat 前面是字母,不是边界)
/\Bcat/.test("a cat"); // false (cat 前面是空格,是边界)经典对比:写 cat 不加边界,会连 catalog、concat 里的 "cat" 也匹配上;加边界后才只匹配独立单词。日常用得最多的两个场景是精确匹配单词和检测重复单词(用反向引用配合,见分组一章)。
多行模式
默认情况下,脱字符和美元只匹配整个字符串的开头和结尾。但很多场景下你的输入是多行文本(中间有换行符),希望锚点能匹配每一行的头尾——这时就加 m 标志(multiline)。
// 多行模式(m 标志)如何改变 ^ $ 的含义
// 默认(无 m):^ $ 只匹配整个字符串的开头和结尾
/^foo/.test("bar\nfoo"); // false (^ 只是整个字符串开头)
/foo$/.test("foo\nbar"); // false ($ 只是整个字符串结尾)
// 加 m 标志:^ $ 匹配每行的开头和结尾
/^foo/m.test("bar\nfoo"); // true (匹配第二行开头)
/foo$/m.test("foo\nbar"); // true (匹配第一行结尾)
// 实例:统计每行以数字开头的行
"text\n1abc\n2def\nxyz".match(/^\d/mg);
// ["1", "2"] (注意加了 g 找全部)
// 实例:删掉每行行尾的空白
"line1 \nline2\t".replace(/\s+$/mg, "");
// "line1\nline2"
// 注意:\b 不受 m 标志影响,它本来就是按"字符类型"判断边界的注意:单词边界不受多行模式影响——它本来就是按"字符类型"判断的,和换行无关。多行模式只改变脱字符和美元的行为。
实战组合
真实项目里,锚点几乎从不单独出现,总是和字符类、量词、分组组合。看几个典型场景:
// 锚点的实战组合
// 1. 校验整段输入是否符合格式(两端锚定)
/^1[3-9]\d{9}$/.test("13812345678"); // 手机号
/^\d{6}$/.test("100000"); // 邮编
/^[A-Za-z][A-Za-z0-9_]{3,15}$/.test("hello_world"); // 用户名
// 2. 提取每行的某个字段
const lines = "name: Alice\nage: 30\ncity: BJ";
const age = lines.match(/^age:\s*(\d+)/m);
// ["age: 30", "30"] (用 m 在多行里定位)
// 3. 替换每一行开头的注释符号
"// line1\n// line2".replace(/^\/\//mg, "#");
// "# line1\n# line2"
// 4. 校验同时包含锚点 + 字符类 + 量词
/^[A-Z][a-z]+ \d{4}$/.test("Hello 2026"); // true- 表单校验:两端锚定,确保整段输入合法,杜绝前后多余字符。
- 多行处理:配合
m标志,从配置文件、日志里按行提取字段。 - 批量替换:删行首空白、改注释符号、加行号前缀,都用
m+ 行首锚点。
小结
- 锚点匹配"位置"不是"字符",零宽,不前进。
- 脱字符、美元在多行模式
m下匹配每行头尾,否则只匹配整个字符串头尾。 - 单词边界是单词字符与非单词字符的交界,不受
m影响。 - 表单校验标准写法:开头锚点 + 模式 + 结尾锚点,确保整段匹配。
下一章讲分组与捕获——圆括号在正则里既是"分组工具"也是"提取数据的钥匙"。
← 上一篇 量词
下一篇 分组与捕获 →