正则表达式完全指南:元字符/量词/分组/断言

小飞兽 正则 6 次阅读 2026-07-29

Introduction

正则表达式(Regular Expression)是处理字符串的强大工具,广泛用于表单验证、文本搜索替换、数据提取等场景。无论是 JavaScript、Python 还是 PHP,几乎所有编程语言都支持正则。本指南系统讲解正则的核心概念——元字符、量词、分组、断言,助你从零到精通正则表达式。

基础语法

1. 元字符(Metacharacters)

.   匹配除换行外任意字符
\d 匹配数字(0-9)
\D 匹配非数字
\w 匹配字母、数字、下划线([A-Za-z0-9_])
\W 匹配非\w
\s 匹配空白字符(空格、制表、换行)
\S 匹配非空白字符
\b 匹配单词边界
^   匹配字符串开头
$   匹配字符串结尾
\. \* \+ \? \\ 转义元字符
[abc] 匹配 a、b 或 c
[^abc] 匹配除了 a、b、c 以外的字符
[a-z] 匹配小写字母

2. 量词(Quantifiers)

*   匹配0次或多次(等价于 {0,})
+   匹配1次或多次(等价于 {1,})
?   匹配0次或1次(等价于 {0,1})
{n}     恰好 n 次
{n,}    至少 n 次
{n,m}   n 到 m 次
.*   贪婪:匹配尽可能多
.*?  非贪婪:匹配尽可能少

3. 分组与捕获

(\d{4})-(\d{2})-(\d{2}) 捕获年、月、日三组
(?:\d{4}) 非捕获组
(?<year>\d{4}) 命名捕获组(ES2018)
(['"])(.*?)\1 反向引用
cat|dog 匹配 'cat' 或 'dog'

4. 断言(Lookahead / Lookbehind)

(?=...) 正向先行断言 — "后面跟着..."
(?!...) 负向先行断言 — "后面不跟..."
(?<=...) 正向后行断言 — "前面是..."(ES2018)
(?<!...) 负向后行断言 — "前面不是..."

完整代码示例

const str = 手机:13812345678 邮箱:zhangsan@example.com 网站:https://www.example.com IP地址:192.168.1.100 日期:2024-01-15 人民币:¥1000.00 美元:$599.00;

const mobileRegex = /^1[3-9]\d{9}$/;
const mobiles = str.match(/1[3-9]\d{9}/g);
console.log('手机号:', mobiles);

const dateRegex = /(\d{4})-(\d{2})-(\d{2})/;
const dateMatch = str.match(dateRegex);
console.log('日期:', dateMatch?.[0], '年:', dateMatch?.[1], '月:', dateMatch?.[2], '日:', dateMatch?.[3]);

const emailRegex = /[\w.-]+@[\w.-]+\.\w+/g;
console.log('邮箱:', str.match(emailRegex));

const urlRegex = /https?:\/\/[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=.]*/g;
console.log('网址:', str.match(urlRegex));

const ipRegex = /\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b/g;
console.log('IP地址:', str.match(ipRegex));

const rmbRegex = /¥(\d+(?:\.\d{2})?)/;
const usdRegex = /\$(\d+(?:\.\d{2})?)/;
console.log('人民币:', str.match(rmbRegex)?.[0], '金额:', str.match(rmbRegex)?.[1]);
console.log('美元:', str.match(usdRegex)?.[0], '金额:', str.match(usdRegex)?.[1]);

const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[A-Za-z\d]{8,}$/;
console.log('密码验证:', passwordRegex.test('Pass1234'));

const htmlRegex = /<[^>]+>/g;
const cleanText = str.replace(htmlRegex, '');
console.log('去除HTML标签后:', cleanText);

const toSnakeCase = (str) => str.replace(/[A-Z]/g, letter => _${letter.toLowerCase()});
console.log('驼峰转下划线:', toSnakeCase('userNameOfTheApplication'));

const highlight = (text, keyword) => text.replace(new RegExp((${keyword}), 'g'), '$1');
console.log('高亮关键词:', highlight('正则表达式很强大,正则表达式很有用', '正则'));

const quotedRegex = /(['"])(.*?)\1/g;
console.log('引号内容:', str.match(quotedRegex));

const namedDateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const namedMatch = str.match(namedDateRegex);
console.log('命名捕获:', namedMatch?.groups);

常见问题

    • 贪婪和非贪婪(惰性)如何选择? 默认是贪婪(尽可能多匹配),当需要精确匹配时应使用非贪婪(加 ?)。例如匹配 HTML 标签内容,应用 <div>.*?</div> 而非 <div>.*</div>
    • 为什么有的正则匹配不到中文? 字符类 [a-z] 只匹配 ASCII 字符,匹配中文要用 [\u4e00-\u9fa5] 或 Unicode 属性。
    • 正则表达式性能如何优化? 避免使用 .* 这种贪婪模式,改用非贪婪或明确字符集;避免回溯,使用锚点(^$)限定范围。
    • lookbehind(后行断言)浏览器支持情况? Chrome 62+、Firefox 78+、Safari 16.4+ 已支持。

延伸阅读