常用正则表达式示例
2025年3月7日大约 13 分钟
常用正则表达式示例
正则表达式在实际开发中有广泛的应用。本文将提供一系列常用的正则表达式示例,如邮箱验证、URL匹配、日期格式检查等,并解释它们的工作原理。
基本验证模式
1. 电子邮件验证
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
// 测试
console.log(emailRegex.test('user@example.com')); // true
console.log(emailRegex.test('user.name+tag@example.co.uk')); // true
console.log(emailRegex.test('invalid@email')); // false (缺少顶级域名)
console.log(emailRegex.test('user@.com')); // false (域名格式错误)
解析:
^[a-zA-Z0-9._%+-]+
- 匹配邮箱名称部分,允许字母、数字和特定符号(._%+-
)@
- 匹配@符号[a-zA-Z0-9.-]+
- 匹配域名部分,允许字母、数字、点和连字符\.
- 匹配点号(转义)[a-zA-Z]{2,}$
- 匹配顶级域名,至少2个字母
2. URL验证
const urlRegex = /^(https?:\/\/)?(www\.)?[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+(\/[a-zA-Z0-9-._~:/?#[\]@!$&'()*+,;=]*)?$/;
// 测试
console.log(urlRegex.test('https://www.example.com')); // true
console.log(urlRegex.test('http://example.com/path?query=1')); // true
console.log(urlRegex.test('www.example.com')); // true
console.log(urlRegex.test('example.com')); // true
console.log(urlRegex.test('https://invalid')); // false (缺少顶级域名)
解析:
^(https?:\/\/)?
- 可选的协议部分(http:// 或 https://)(www\.)?
- 可选的www前缀[a-zA-Z0-9-]+
- 域名主体部分(\.[a-zA-Z0-9-]+)+
- 至少一个子域名或顶级域名(\/[a-zA-Z0-9-._~:/?#[\]@!$&'()*+,;=]*)?$
- 可选的路径部分
3. 中国手机号码验证
const cnMobileRegex = /^1[3-9]\d{9}$/;
// 测试
console.log(cnMobileRegex.test('13812345678')); // true
console.log(cnMobileRegex.test('19912345678')); // true
console.log(cnMobileRegex.test('12345678901')); // false (不是1开头+3-9的号段)
console.log(cnMobileRegex.test('1381234567')); // false (位数不足)
解析:
^1
- 以1开头[3-9]
- 第二位是3到9之间的数字(覆盖目前所有号段)\d{9}$
- 后面跟9个数字,总共11位
4. 中国身份证号码验证
// 18位身份证号码(简化版,不包含校验码验证)
const idCardRegex = /^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
// 测试
console.log(idCardRegex.test('110101199001011234')); // true
console.log(idCardRegex.test('11010119900101123X')); // true
console.log(idCardRegex.test('110101990101123X')); // false (年份格式错误)
解析:
^[1-9]\d{5}
- 6位地区码,首位不为0(19|20)\d{2}
- 出生年份,限定为19xx或20xx(0[1-9]|1[0-2])
- 出生月份,01-12(0[1-9]|[12]\d|3[01])
- 出生日期,01-31\d{3}
- 3位顺序码[\dXx]$
- 最后一位校验码,可以是数字或X/x
5. 邮政编码(中国)
const postalCodeRegex = /^[1-9]\d{5}$/;
// 测试
console.log(postalCodeRegex.test('100001')); // true
console.log(postalCodeRegex.test('012345')); // false (首位为0)
console.log(postalCodeRegex.test('1234567')); // false (超过6位)
解析:
^[1-9]
- 首位为1-9的数字(不能为0)\d{5}$
- 后面跟5个数字,总共6位
数据格式验证
1. 日期格式验证
// YYYY-MM-DD 格式
const dateRegex = /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
// 测试
console.log(dateRegex.test('2023-05-15')); // true
console.log(dateRegex.test('2023-13-15')); // false (月份无效)
console.log(dateRegex.test('2023-02-30')); // true (注意:这里只验证格式,不验证日期有效性)
解析:
^(\d{4})
- 4位年份-(0[1-9]|1[0-2])
- 月份,01-12-(0[1-9]|[12]\d|3[01])$
- 日期,01-31
注意
上面的正则表达式只验证日期格式,不验证日期的有效性(如2月30日)。如需完整验证,应结合JavaScript的Date对象进行检查。
2. 时间格式验证
// HH:MM:SS 格式(24小时制)
const timeRegex = /^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)$/;
// 测试
console.log(timeRegex.test('13:45:30')); // true
console.log(timeRegex.test('24:00:00')); // false (小时超过23)
console.log(timeRegex.test('12:60:30')); // false (分钟超过59)
解析:
^([01]\d|2[0-3])
- 小时,00-23:([0-5]\d)
- 分钟,00-59:([0-5]\d)$
- 秒,00-59
3. IP地址验证
// IPv4地址
const ipv4Regex = /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){2}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/;
// 测试
console.log(ipv4Regex.test('192.168.1.1')); // true
console.log(ipv4Regex.test('255.255.255.255')); // true
console.log(ipv4Regex.test('256.168.1.1')); // false (256超出范围)
console.log(ipv4Regex.test('192.168.1')); // false (段数不足)
解析:
(25[0-5]|2[0-4]\d|[01]?\d\d?)
- 匹配0-255的数字25[0-5]
- 匹配250-2552[0-4]\d
- 匹配200-249[01]?\d\d?
- 匹配0-199
\.
- 匹配点号- 整体模式确保四段都在有效范围内
4. MAC地址验证
// MAC地址(支持多种格式)
const macRegex = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
// 测试
console.log(macRegex.test('00:1B:44:11:3A:B7')); // true (冒号分隔)
console.log(macRegex.test('00-1B-44-11-3A-B7')); // true (连字符分隔)
console.log(macRegex.test('00:1B:44:11:3A')); // false (段数不足)
解析:
([0-9A-Fa-f]{2}[:-]){5}
- 匹配5组由冒号或连字符分隔的两位十六进制数([0-9A-Fa-f]{2})
- 最后一组两位十六进制数
文本格式验证
1. 密码强度验证
// 强密码:至少8位,包含大小写字母、数字和特殊字符
const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,}$/;
// 测试
console.log(strongPasswordRegex.test('Passw0rd!')); // true
console.log(strongPasswordRegex.test('password')); // false (缺少大写字母、数字和特殊字符)
console.log(strongPasswordRegex.test('PASSWORD1!')); // false (缺少小写字母)
解析:
(?=.*[a-z])
- 前瞻断言,确保包含至少一个小写字母(?=.*[A-Z])
- 前瞻断言,确保包含至少一个大写字母(?=.*\d)
- 前瞻断言,确保包含至少一个数字(?=.*[!@#$%^&*])
- 前瞻断言,确保包含至少一个特殊字符[A-Za-z\d!@#$%^&*]{8,}
- 匹配由字母、数字和特定特殊字符组成的至少8位的字符串
2. 用户名验证
// 用户名:字母开头,只包含字母、数字和下划线,长度6-20
const usernameRegex = /^[a-zA-Z][a-zA-Z0-9_]{5,19}$/;
// 测试
console.log(usernameRegex.test('user123')); // true
console.log(usernameRegex.test('user_123')); // true
console.log(usernameRegex.test('123user')); // false (不以字母开头)
console.log(usernameRegex.test('user')); // false (长度不足)
解析:
^[a-zA-Z]
- 以字母开头[a-zA-Z0-9_]{5,19}
- 后面跟5-19个字母、数字或下划线字符(总长度6-20)
3. 中文字符验证
// 匹配中文字符
const chineseRegex = /^[\u4e00-\u9fa5]+$/;
// 测试
console.log(chineseRegex.test('你好世界')); // true
console.log(chineseRegex.test('Hello世界')); // false (包含非中文字符)
解析:
[\u4e00-\u9fa5]
- 匹配Unicode范围内的中文字符+
- 匹配一个或多个中文字符
4. 文件扩展名验证
// 图片文件扩展名
const imageExtRegex = /\.(jpg|jpeg|png|gif|bmp|webp)$/i;
// 测试
console.log(imageExtRegex.test('image.jpg')); // true
console.log(imageExtRegex.test('image.JPG')); // true (忽略大小写)
console.log(imageExtRegex.test('document.pdf')); // false (非图片扩展名)
解析:
\.
- 匹配点号(jpg|jpeg|png|gif|bmp|webp)
- 匹配指定的图片扩展名$
- 确保扩展名在字符串末尾i
- 忽略大小写标志
数据提取模式
1. 提取HTML标签
// 提取HTML标签
const htmlTagRegex = /<([a-z]+)([^<]+)*(?:>(.*?)<\/\1>|\s+\/>)/gi;
// 测试
const html = '<div class="container">Content</div><img src="image.jpg" />';
const tags = [...html.matchAll(htmlTagRegex)];
console.log(tags.map(tag => tag[0]));
// 输出: ['<div class="container">Content</div>', '<img src="image.jpg" />']
解析:
<([a-z]+)
- 匹配开始标签和标签名([^<]+)*
- 匹配标签属性(?:>(.*?)<\/\1>|\s+\/>)
- 非捕获组,匹配两种情况:>(.*?)<\/\1>
- 匹配标签内容和结束标签,其中\1
引用第一个捕获组(标签名)\s+\/>
- 匹配自闭合标签
2. 提取URL
// 提取URL
const urlExtractRegex = /(https?:\/\/[^\s]+)/g;
// 测试
const text = '请访问 https://example.com 和 http://example.org/path?query=1 获取更多信息。';
const urls = [...text.matchAll(urlExtractRegex)].map(match => match[1]);
console.log(urls);
// 输出: ['https://example.com', 'http://example.org/path?query=1']
解析:
(https?:\/\/[^\s]+)
- 捕获以http://或https😕/开头,到空白字符结束的所有内容g
- 全局标志,查找所有匹配项
3. 提取电子邮件地址
// 提取电子邮件地址
const emailExtractRegex = /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g;
// 测试
const text = '联系方式:user@example.com 或 support@company.co.uk';
const emails = [...text.matchAll(emailExtractRegex)].map(match => match[1]);
console.log(emails);
// 输出: ['user@example.com', 'support@company.co.uk']
解析:
- 使用与电子邮件验证相同的模式,但包装在捕获组中并添加全局标志
4. 提取图片链接
// 提取HTML中的图片链接
const imgSrcRegex = /<img[^>]+src="([^"]+)"/g;
// 测试
const html = '<div><img src="image1.jpg" alt="Image 1"><img src="image2.png" width="100"></div>';
const imgSrcs = [];
let match;
while ((match = imgSrcRegex.exec(html)) !== null) {
imgSrcs.push(match[1]);
}
console.log(imgSrcs);
// 输出: ['image1.jpg', 'image2.png']
解析:
<img[^>]+
- 匹配img标签开始和任何属性src="([^"]+)"
- 匹配src属性并捕获其值
文本处理模式
1. 驼峰命名转换
// 驼峰命名转换为短横线命名
function camelToKebab(str) {
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}
// 测试
console.log(camelToKebab('backgroundColor')); // "background-color"
console.log(camelToKebab('userProfileData')); // "user-profile-data"
解析:
([a-z])([A-Z])
- 捕获小写字母后跟大写字母的模式'$1-$2'
- 替换为第一个捕获组、连字符和第二个捕获组toLowerCase()
- 将结果转换为小写
2. 短横线命名转换
// 短横线命名转换为驼峰命名
function kebabToCamel(str) {
return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
}
// 测试
console.log(kebabToCamel('background-color')); // "backgroundColor"
console.log(kebabToCamel('user-profile-data')); // "userProfileData"
解析:
-([a-z])
- 捕获连字符后跟小写字母的模式- 使用替换函数将捕获的字母转换为大写
3. 格式化数字
// 添加千位分隔符
function formatNumber(num) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
// 测试
console.log(formatNumber(1234567)); // "1,234,567"
console.log(formatNumber(1000000)); // "1,000,000"
解析:
\B
- 匹配非单词边界(?=(\d{3})+(?!\d))
- 前瞻断言,匹配位置后面是3的倍数个数字且之后没有更多数字
4. 清理HTML标签
// 移除HTML标签
function stripHtml(html) {
return html.replace(/<[^>]*>/g, '');
}
// 测试
console.log(stripHtml('<p>这是<strong>一些</strong>文本</p>'));
// 输出: "这是一些文本"
解析:
<[^>]*>
- 匹配HTML标签(从<开始到>结束的所有内容)
高级模式
1. 信用卡号码格式化
// 格式化信用卡号码(每4位添加空格)
function formatCreditCard(cardNumber) {
// 先移除所有非数字字符
const cleaned = cardNumber.replace(/\D/g, '');
// 每4位添加空格
return cleaned.replace(/(\d{4})(?=\d)/g, '$1 ');
}
// 测试
console.log(formatCreditCard('1234567890123456')); // "1234 5678 9012 3456"
console.log(formatCreditCard('1234-5678-9012-3456')); // "1234 5678 9012 3456"
解析:
\D
- 匹配任何非数字字符(\d{4})(?=\d)
- 捕获4个数字,且后面还有数字
2. 电话号码格式化
// 格式化中国手机号码
function formatChinesePhone(phone) {
// 移除所有非数字字符
const cleaned = phone.replace(/\D/g, '');
// 格式化为 3-4-4 格式
return cleaned.replace(/^(\d{3})(\d{4})(\d{4})$/, '$1-$2-$3');
}
// 测试
console.log(formatChinesePhone('13812345678')); // "138-1234-5678"
console.log(formatChinesePhone('138 1234 5678')); // "138-1234-5678"
解析:
^(\d{3})(\d{4})(\d{4})$
- 将11位手机号分成3组,分别捕获前3位、中间4位和后4位
3. 提取代码块
// 提取Markdown代码块
const codeBlockRegex = /```([a-z]*)\n([\s\S]*?)```/g;
// 测试
const markdown = `
这是一段文本。
\`\`\`javascript
function hello() {
console.log('Hello, world!');
}
\`\`\`
这是另一段文本。
\`\`\`css
body {
background-color: #f0f0f0;
}
\`\`\`
`;
const codeBlocks = [];
let match;
while ((match = codeBlockRegex.exec(markdown)) !== null) {
codeBlocks.push({
language: match[1],
code: match[2]
});
}
console.log(codeBlocks);
解析:
```([a-z]*)\n
- 匹配代码块开始标记和可选的语言标识([\s\S]*?)
- 非贪婪地匹配任何字符(包括换行)```
- 匹配代码块结束标记
4. 验证颜色代码
// 验证十六进制颜色代码
const hexColorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
// 测试
console.log(hexColorRegex.test('#FFF')); // true
console.log(hexColorRegex.test('#123ABC')); // true
console.log(hexColorRegex.test('#WXYZ')); // false (包含无效字符)
console.log(hexColorRegex.test('#12345')); // false (长度不正确)
解析:
^#
- 以#开头([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})
- 匹配6位或3位十六进制字符$
- 确保没有其他字符
实用函数
1. 验证表单字段
// 表单验证工具函数
const validators = {
email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
phone: /^1[3-9]\d{9}$/,
username: /^[a-zA-Z][a-zA-Z0-9_]{5,19}$/,
password: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,}$/,
url: /^(https?:\/\/)?(www\.)?[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)+(\/[a-zA-Z0-9-._~:/?#[\]@!$&'()*+,;=]*)?$/
};
function validateField(fieldName, value) {
if (!validators[fieldName]) {
return { valid: false, error: '未知字段类型' };
}
const isValid = validators[fieldName].test(value);
let errorMessage = '';
if (!isValid) {
switch (fieldName) {
case 'email':
errorMessage = '请输入有效的电子邮件地址';
break;
case 'phone':
errorMessage = '请输入有效的手机号码';
break;
case 'username':
errorMessage = '用户名必须以字母开头,只包含字母、数字和下划线,长度6-20';
break;
case 'password':
errorMessage = '密码必须至少8位,包含大小写字母、数字和特殊字符';
break;
case 'url':
errorMessage = '请输入有效的URL';
break;
}
}
return {
valid: isValid,
error: errorMessage
};
}
// 测试
console.log(validateField('email', 'user@example.com'));
console.log(validateField('phone', '13812345678'));
console.log(validateField('username', 'user123'));
console.log(validateField('password', 'Passw0rd!'));
console.log(validateField('url', 'https://example.com'));
2. 提取所有链接
// 提取文本中的所有链接
function extractLinks(text) {
const urlRegex = /(https?:\/\/[^\s]+)/g;
const emailRegex = /([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g;
const urls = [];
const emails = [];
let match;
while ((match = urlRegex.exec(text)) !== null) {
urls.push(match[1]);
}
while ((match = emailRegex.exec(text)) !== null) {
emails.push(match[1]);
}
return { urls, emails };
}
// 测试
const text = '联系我们:support@example.com 或访问 https://example.com 获取更多信息。';
console.log(extractLinks(text));
3. 敏感信息脱敏
// 敏感信息脱敏
function maskSensitiveInfo(text) {
// 手机号码脱敏
const maskedPhone = text.replace(/(\d{3})\d{4}(\d{4})/g, '$1****$2');
// 身份证号码脱敏
const maskedIdCard = maskedPhone.replace(/(\d{6})\d{8}(\d{4})/g, '$1********$2');
// 邮箱脱敏
return maskedIdCard.replace(/([a-zA-Z0-9._%+-]{2})[a-zA-Z0-9._%+-]+(@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g, '$1***$2');
}
// 测试
const info = '姓名:张三,手机:13812345678,身份证:110101199001011234,邮箱:zhangsan@example.com';
console.log(maskSensitiveInfo(info));
// 输出: "姓名:张三,手机:138****5678,身份证:110101********1234,邮箱:zh***@example.com"
练习
编写一个正则表达式,验证中国车牌号(普通汽车,如"京A12345")。
创建一个函数,使用正则表达式将数字转换为中文大写金额(如"1234.56"转换为"壹仟贰佰叁拾肆元伍角陆分")。
编写一个正则表达式,从HTML文本中提取所有图片的alt属性值。
创建一个函数,使用正则表达式验证密码强度,并返回详细的强度评估(如包含大小写字母、数字、特殊字符等)。
编写一个正则表达式,匹配中国大陆的座机号码(区号+号码,如"010-12345678"或"0755-8888888")。
总结
正则表达式是处理文本的强大工具,在实际开发中有广泛的应用。本文提供了多种常用的正则表达式示例,涵盖了基本验证、数据格式验证、文本处理和高级应用等方面。
通过学习和理解这些示例,您可以:
- 掌握常见的正则表达式模式和技巧
- 了解如何构建和优化正则表达式
- 学会使用正则表达式解决实际问题
- 提高文本处理和数据验证的效率
在使用正则表达式时,需要注意以下几点:
- 正则表达式功能强大但也容易变得复杂,应尽量保持简洁明了
- 对于复杂的文本处理任务,可能需要结合其他方法或工具
- 测试是确保正则表达式正确性的关键,应该使用多种情况进行测试
- 考虑性能因素,避免使用可能导致灾难性回溯的模式
通过练习和实践,您可以逐步提高正则表达式的编写和使用能力,使其成为您开发工具箱中的得力助手。