正则表达式入门到精通

从基础语法到高级技巧,全面掌握正则表达式的使用方法。包含常用模式、代码示例和实战技巧。

开发基础 2026-05-27 10 分钟

正则表达式入门到精通

正则表达式(Regular Expression,简称regex)是处理文本的强大工具。无论是数据验证、文本提取还是字符串替换,正则表达式都能高效完成。本文从基础语法到高级技巧,帮助你全面掌握正则表达式。

基础语法

字面量字符

最简单的正则就是匹配字面量字符:

/hello/.test('hello world')  // true
/world/.test('hello world')  // true

元字符

元字符 含义 示例
. 匹配任意字符(除换行) a.c 匹配 “abc”、“a1c”
\d 匹配数字 [0-9] \d+ 匹配 “123”
\w 匹配单词字符 [a-zA-Z0-9_] \w+ 匹配 “hello_123”
\s 匹配空白字符 \s+ 匹配空格、制表符
\b 匹配单词边界 \bword\b 匹配独立的 “word”
^ 匹配字符串开头 ^Hello 匹配以Hello开头
$ 匹配字符串结尾 world$ 匹配以world结尾

量词

量词 含义 示例
* 0次或多次 ab* 匹配 “a”、“ab”、“abb”
+ 1次或多次 ab+ 匹配 “ab”、“abb”,不匹配 “a”
? 0次或1次 colou?r 匹配 “color” 和 “colour”
{n} 恰好n次 \d{3} 匹配三位数字
{n,m} n到m次 \d{2,4} 匹配2到4位数字

字符类

方括号[]定义字符类,匹配其中任意一个字符:

/[aeiou]/        // 匹配任意元音字母
/[a-z]/          // 匹配任意小写字母
/[A-Za-z0-9]/    // 匹配任意字母或数字
/[^abc]/         // 匹配除a、b、c以外的字符(取反)

分组与捕获

捕获组

圆括号()创建捕获组,可以提取匹配的子串:

const match = '2026-05-28'.match(/(\d{4})-(\d{2})-(\d{2})/)
console.log(match[1])  // "2026"(年)
console.log(match[2])  // "05"(月)
console.log(match[3])  // "28"(日)

非捕获组

(?:)创建非捕获组,只分组不捕获:

/h(?:ello|i) world/  // 匹配 "hello world" 或 "hi world"

命名捕获组

ES2018支持命名捕获组,更易读:

const match = '2026-05-28'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/)
console.log(match.groups.year)   // "2026"
console.log(match.groups.month)  // "05"

常用正则模式

邮箱验证

const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
emailRegex.test('user@example.com')   // true
emailRegex.test('invalid-email')      // false

手机号验证(中国大陆)

const phoneRegex = /^1[3-9]\d{9}$/
phoneRegex.test('13812345678')   // true
phoneRegex.test('12345678901')   // false

URL验证

const urlRegex = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)$/
urlRegex.test('https://example.com/path?q=1')  // true

身份证号验证(中国大陆)

const idCardRegex = /^\d{17}[\dXx]$/
idCardRegex.test('110101199003074518')  // true(简化版验证)

HTML标签提取

const tagRegex = /<([a-z]+)[^>]*>(.*?)<\/\1>/gi
'<b>bold</b> and <i>italic</i>'.match(tagRegex)
// ["<b>bold</b>", "<i>italic</i>"]

常用操作

字符串替换

// 替换所有空格为连字符
'hello world foo'.replace(/\s+/g, '-')  // "hello-world-foo"

// 驼峰命名转换
'background-color'.replace(/-([a-z])/g, (_, c) => c.toUpperCase())
// "backgroundColor"

// 去除首尾空格
'  hello  '.replace(/^\s+|\s+$/g, '')  // "hello"

字符串分割

// 按多种分隔符分割
'a,b;c d|e'.split(/[,;|\s]+/)  // ["a", "b", "c", "d", "e"]

提取所有匹配

// 提取所有数字
'abc123def456'.match(/\d+/g)  // ["123", "456"]

// 提取所有链接
const html = '<a href="https://a.com">A</a><a href="https://b.com">B</a>'
html.match(/href="([^"]+)"/g)  // ["href=\"https://a.com\"", "href=\"https://b.com\""]

高级技巧

零宽断言

// 前瞻断言:匹配后面跟着特定内容的位置
'hello123world'.match(/\d+(?=world)/)  // "123"

// 后顾断言:匹配前面有特定内容的位置
'$100 €200'.match(/(?<=\$)\d+/)  // "100"

// 负前瞻:匹配后面不跟特定内容的位置
'hello123world456foo'.match(/\d+(?!world)/)  // "456"

贪婪与非贪婪

默认量词是贪婪的(尽可能多匹配),加?变为非贪婪:

// 贪婪匹配
'<div>hello</div><div>world</div>'.match(/<div>.*<\/div>/)
// ["<div>hello</div><div>world</div>"]

// 非贪婪匹配
'<div>hello</div><div>world</div>'.match(/<div>.*?<\/div>/)
// ["<div>hello</div>"]

标志位

标志 含义
g 全局匹配(匹配所有结果)
i 忽略大小写
m 多行模式(^和$匹配每行)
s dotAll模式(.匹配换行符)
u Unicode模式

调试技巧

  1. 分步构建 — 复杂正则拆分为多个简单部分逐步测试
  2. 使用在线工具regex101.com 可视化正则匹配过程
  3. 添加注释 — 复杂正则使用x模式(忽略空白)添加注释
  4. 避免灾难性回溯 — 嵌套量词(a+)+可能导致性能问题

总结

正则表达式是文本处理的瑞士军刀。掌握基础语法后,通过大量实践积累常用模式,就能在开发中高效处理各种文本匹配需求。记住:好的正则应该简洁明了,过于复杂的正则难以维护。

📚 相关文章