常用正则表达式

前端开发必备:常用正则表达式整理

做前端开发这么久,正则表达式绝对是我又爱又恨的工具——爱它能一行代码搞定复杂的表单验证、文本提取,恨它稍不注意就写错,调试半天找不到问题。
前阵子整理项目里的正则,发现很多网上的老正则已经过时(比如手机号段还停留在13/15开头),还有不少转义错误。今天就把我实战中验证过、修正过的常用正则全部分享出来,附详细解释和避坑指南,看完直接就能用到项目里。

一、先搞懂:正则的3个核心方法

在看具体正则之前,先快速回顾下前端最常用的3个正则方法,这是我们使用正则的基础:

方法 作用 示例
test() 检查字符串是否匹配正则,返回布尔值 true/false /^1[3-9]\d{9}$/.test('13812345678')
match() 在字符串中查找匹配的内容,返回匹配结果数组(无匹配返回 null 'abc123def'.match(/\d+/)['123']
replace() 替换字符串中匹配的内容,返回新字符串 'a b c'.replace(/\s+/g, ' ') 'a b c'

小技巧:正则字面量(/正则/)比 new RegExp('正则') 更常用,因为不用处理双转义的问题(比如 \d 在字符串里要写成 \\d)。

二、身份信息类:表单验证最常用

这是项目里用得最多的场景,身份证、手机号、邮箱、邮编,一个都不能少。

1. 身份证号码(15位/18位)

身份证正则不仅要校验长度,还要校验年份、月份、日期的基本格式,最后一位校验位(X/x)也要支持。

1
2
3
4
5
6
7
8
9
10
11
12
// 15位身份证:1-9开头,7位出生日期(YYMMDD),3位顺序码
const idCard15 = /^[1-9]\d{7}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}$/;

// 18位身份证:1-9开头,6位地区码,8位出生日期(YYYYMMDD),3位顺序码,1位校验位(0-9/X/x)
const idCard18 = /^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;

// 合并版:同时支持15位和18位
const idCard = /(^[1-9]\d{7}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}$)|(^[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(idCard.test('110101199003077758')); // true(18位)
console.log(idCard.test('110101900307775')); // true(15位)

⚠️ 避坑指南

  • 正则只能校验格式,不能校验身份证的真实性(比如校验位是否正确、地区码是否存在)。如果需要严格校验,建议配合校验算法(比如ISO 7064:1983.MOD 11-2)使用。
  • 注意年份限制:上面的18位正则只支持1900-2099年,这已经能覆盖绝大多数场景了。

2. 中国大陆手机号(2024年最新号段)

手机号段更新很快,现在不仅有13/15/17/18/14开头,还有16/19开头的新号段,正则必须跟上。

1
2
3
4
5
6
7
8
9
10
// 中国大陆手机号:1开头,第二位3-9,后面9位数字
const phone = /^1[3-9]\d{9}$/;

// 带国际区号(+86或0086)的版本
const phoneWithArea = /^(\+86|0086)?1[3-9]\d{9}$/;

// 使用示例
console.log(phone.test('13812345678')); // true
console.log(phone.test('19912345678')); // true(19开头新号段)
console.log(phoneWithArea.test('+8613812345678')); // true

⚠️ 避坑指南

  • 不要写太复杂的号段细分(比如 13[0-9]|15[0-35-9]|...),号段更新太快,维护成本太高。用 1[3-9]\d{9} 覆盖所有1开头的11位数字,是最稳妥的方案。
  • 如果需要区分移动/联通/电信,再单独写细分正则,但一般业务场景不需要。

3. 邮箱地址

邮箱正则要覆盖常见格式:用户名@域名.后缀,支持用户名里的 +.-_ 等特殊字符。

1
2
3
4
5
6
// 通用邮箱正则
const email = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

// 使用示例
console.log(email.test('user_name+tag@example.co.uk')); // true(支持+标签、多级域名)
console.log(email.test('user.name@example.com')); // true

⚠️ 避坑指南

  • 没有100%覆盖所有RFC标准的邮箱正则(太复杂,性能也差),上面的正则能覆盖99.9%的实际场景。
  • 不要用正则限制邮箱长度,RFC标准允许邮箱最长254个字符。

4. 中国邮政编码

6位数字,第一位不为0。

1
2
3
4
const zipCode = /^[1-9]\d{5}$/;

// 使用示例
console.log(zipCode.test('430000')); // true

三、日期时间类:格式校验必备

日期格式校验很常见,要支持常见的 YYYY-MM-DDYYYY/MM/DDHH:mm:ss 等格式。

1. 日期(YYYY-MM-DD 或 YYYY/MM/DD)

1
2
3
4
5
6
// 支持 - 或 / 分隔,年份1900-2099,月份01-12,日期01-31
const date = /^(19|20)\d{2}([-\/])(0[1-9]|1[0-2])\2(0[1-9]|[12]\d|3[01])$/;

// 使用示例
console.log(date.test('2024-05-20')); // true
console.log(date.test('2024/05/20')); // true

2. 时间(HH:mm:ss 或 HH:mm)

1
2
3
4
5
6
7
8
9
// 时间:HH:mm:ss(24小时制)
const time = /^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$/;

// 简化版:HH:mm
const timeSimple = /^([01]\d|2[0-3]):[0-5]\d$/;

// 使用示例
console.log(time.test('14:30:00')); // true
console.log(timeSimple.test('14:30')); // true

3. 日期时间(YYYY-MM-DD HH:mm:ss)

1
2
3
4
const dateTime = /^(19|20)\d{2}([-\/])(0[1-9]|1[0-2])\2(0[1-9]|[12]\d|3[01]) ([01]\d|2[0-3]):[0-5]\d:[0-5]\d$/;

// 使用示例
console.log(dateTime.test('2024-05-20 14:30:00')); // true

⚠️ 避坑指南

  • 正则只能校验格式,不能校验逻辑合理性(比如2024-02-30、2024-04-31这种无效日期)。如果需要严格校验,建议用 Date 对象或者 day.js/moment.js 等日期库。

四、数字类:金额、整数、小数全覆盖

1. 整数(支持正负数)

1
2
3
4
5
6
7
8
9
10
11
12
// 整数:正整数、负整数、0
const integer = /^[-+]?\d+$/;

// 正整数(不包含0)
const positiveInteger = /^[1-9]\d*$/;

// 负整数(不包含0)
const negativeInteger = /^-[1-9]\d*$/;

// 使用示例
console.log(integer.test('-123')); // true
console.log(positiveInteger.test('123')); // true

2. 浮点数(小数,支持正负数)

1
2
3
4
5
6
7
8
9
// 浮点数:支持整数部分、小数部分,比如 123、123.45、-123.45、.45
const float = /^[-+]?(\d+(\.\d*)?|\.\d+)$/;

// 严格浮点数(必须有小数点)
const strictFloat = /^[-+]?\d+\.\d+$/;

// 使用示例
console.log(float.test('.45')); // true
console.log(strictFloat.test('123.45')); // true

3. 金额(保留2位小数,支持千分位)

1
2
3
4
5
6
// 金额:支持千分位(可选),保留2位小数,比如 1234.56、1,234.56、12,345.67
const money = /^[-+]?(\d{1,3}(,\d{3})*|\d+)(\.\d{2})?$/;

// 使用示例
console.log(money.test('12,345.67')); // true
console.log(money.test('1234.56')); // true

五、文本提取类:爬虫、数据清洗常用

1. URL链接

1
2
3
4
5
6
// 通用URL:支持 http/https/ftp,域名、路径、参数、哈希
const url = /^(https?:\/\/|ftp:\/\/)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(:\d+)?(\/[a-zA-Z0-9-._~:/?#[\]@!$&'()*+,;=]*)?$/;

// 使用示例
console.log(url.test('https://www.example.com/path?query=123#hash')); // true
console.log(url.test('ftp://ftp.example.com')); // true

2. 图片链接(常见后缀)

1
2
3
4
5
// 图片链接:以 .jpg/.jpeg/.png/.gif/.webp/.bmp 结尾(不区分大小写)
const imgUrl = /^https?:\/\/.*\.(jpg|jpeg|png|gif|webp|bmp)$/i;

// 使用示例
console.log(imgUrl.test('https://example.com/image.JPG')); // true(i修饰符不区分大小写)

3. 中文字符串

1
2
3
4
5
6
7
8
9
// 基本汉字(Unicode范围:\u4e00-\u9fa5)
const chinese = /^[\u4e00-\u9fa5]+$/;

// 包含中文的字符串(至少有一个中文)
const hasChinese = /[\u4e00-\u9fa5]/;

// 使用示例
console.log(chinese.test('你好世界')); // true
console.log(hasChinese.test('你好hello')); // true

4. 去除字符串首尾空格

虽然现在有 String.prototype.trim(),但用正则实现也很经典:

1
2
const trim = /^\s+|\s+$/g;
' hello world '.replace(trim, ''); // 'hello world'

六、其他常用正则

1. 用户名(字母开头,字母数字下划线,4-16位)

1
2
3
4
const username = /^[a-zA-Z][a-zA-Z0-9_]{3,15}$/;

// 使用示例
console.log(username.test('user_123')); // true

2. 密码强度(至少8位,包含大小写字母、数字、特殊字符)

1
2
3
4
5
// 强密码:至少8位,包含大写字母、小写字母、数字、特殊字符(!@#$%^&*)
const strongPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[a-zA-Z\d!@#$%^&*]{8,}$/;

// 使用示例
console.log(strongPassword.test('Abc123!@')); // true

3. QQ号码(5-11位数字,不以0开头)

1
2
3
4
const qq = /^[1-9]\d{4,10}$/;

// 使用示例
console.log(qq.test('123456789')); // true

七、避坑指南:正则的5个常见坑

1. 转义字符的坑

在正则字面量里,\d 表示数字,但如果用 new RegExp() 字符串写法,必须双转义成 \\d

1
2
3
4
5
6
7
8
// 正确:字面量写法
const reg1 = /\d+/;

// 正确:字符串写法(双转义)
const reg2 = new RegExp('\\d+');

// 错误:字符串写法没双转义,会变成 'd+'
const reg3 = new RegExp('\d+');

建议:优先用正则字面量,避免转义问题。

2. 贪婪匹配 vs 懒惰匹配

正则默认是贪婪匹配(尽可能多匹配),在量词后面加 ? 变成懒惰匹配(尽可能少匹配):

1
2
3
4
5
6
7
const str = '<div>hello</div><div>world</div>';

// 贪婪匹配:匹配整个字符串
str.match(/<div>.*<\/div>/); // ['<div>hello</div><div>world</div>']

// 懒惰匹配:只匹配第一个<div>...</div>
str.match(/<div>.*?<\/div>/); // ['<div>hello</div>']

3. 正则的性能问题

复杂的正则(比如大量嵌套、回溯)会导致性能问题,甚至页面卡顿:

  • 避免写太复杂的正则,能拆分成多个小正则就拆分;
  • 避免用 .* 这种大范围匹配,尽量用具体的字符范围;
  • 合理使用 ^$ 锚点,减少不必要的匹配。

4. 不要过度依赖正则

正则不是万能的:

  • 身份证校验位、日期逻辑合理性,用算法或日期库更靠谱;
  • HTML/XML解析,用DOM解析器(比如 DOMParser)比正则更安全;
  • 复杂的语法解析,用专门的解析器。

5. 修饰符的使用

常用修饰符:

  • i:不区分大小写(/abc/i 匹配 ABCAbc);
  • g:全局匹配(/a/g 匹配所有 a,而不是只匹配第一个);
  • m:多行匹配(^$ 匹配每一行的开头和结尾)。

八、写在最后

正则表达式是前端开发的利器,但也是一把双刃剑——用得好能事半功倍,用不好会带来无数调试噩梦。

我的建议是:

  1. 优先用成熟的正则(比如本文整理的这些),不要自己瞎写;
  2. 写好后多测试边界情况(比如空字符串、特殊字符、超长字符串);
  3. 复杂场景配合工具库使用(比如日期用day.js,密码强度用zxcvbn)。

常用正则表达式
https://cszy.top/2015-09-01 常用正则表达式/
作者
csorz
发布于
2015年9月1日
许可协议