@skyroc/utils
Regex
项目常用校验正则常量:用户名、手机号、密码、邮箱、验证码、URL
概述
import {
REG_USER_NAME,
REG_PHONE,
REG_PWD,
REG_EMAIL,
REG_CODE_SIX,
REG_CODE_FOUR,
REG_URL,
} from '@skyroc/utils';reg 模块导出 7 个预定义正则常量,覆盖表单验证中最常见的校验场景。所有正则均为非全局模式(无 g 标志),可安全地在 test() 中复用而不存在状态问题。
正则速查
| 常量 | 规则摘要 | 典型合法值 | 典型非法值 |
|---|---|---|---|
REG_USER_NAME | 4-16 位:中文 / 英文 / 数字 / _ / - | alice_01、张三 | ab(太短)、alice@(含非法字符) |
REG_PHONE | 中国大陆 11 位手机号 | 13812345678 | 12345678901(非法号段) |
REG_PWD | 6-18 位:字母 / 数字 / _ | pass_123 | abc(太短)、pass word(含空格) |
REG_EMAIL | 标准邮箱格式 | user@example.com | user@、@example.com |
REG_CODE_SIX | 恰好 6 位纯数字 | 123456 | 12345(5 位)、1234567(7 位) |
REG_CODE_FOUR | 恰好 4 位纯数字 | 1234 | 123、12345 |
REG_URL | HTTP / HTTPS URL(含相对路径) | https://example.com/path?q=1 | ftp://…、example(无协议) |
详细说明
REG_USER_NAME — 用户名
/^[\u4E00-\u9FA5a-zA-Z0-9_-]{4,16}$/- 字符集:中文(CJK 基本汉字)+ 英文大小写 + 数字 + 下划线 + 短横线
- 长度限制:4 ~ 16 个字符
- 全字符串匹配(
^和$)
REG_USER_NAME.test('alice'); // true
REG_USER_NAME.test('张三_01'); // true
REG_USER_NAME.test('ab'); // false(太短)
REG_USER_NAME.test('alice@gmail'); // false(@ 非法)
REG_USER_NAME.test('a'.repeat(17)); // false(太长)REG_PHONE — 中国大陆手机号
/^[1](([3][0-9])|([4][01456789])|([5][012356789])|([6][2567])|([7][0-8])|([8][0-9])|([9][012356789]))[0-9]{8}$/- 首位必须为
1 - 第二位按运营商号段精确匹配(覆盖 3x、4x、5x、6x、7x、8x、9x 中的合法号段)
- 后 8 位为任意数字
- 不校验虚拟运营商号段(170/171)等边缘情况
REG_PHONE.test('13812345678'); // true
REG_PHONE.test('19912345678'); // true
REG_PHONE.test('12345678901'); // false(1 开头但号段非法)
REG_PHONE.test('1381234567'); // false(只有 10 位)
REG_PHONE.test('+8613812345678'); // false(含国际区号)如需校验带国际区号的手机号,需使用专门的国际号码校验库(如
libphonenumber-js)。
REG_PWD — 密码
/^\w{6,18}$/- 字符集:
\w=[a-zA-Z0-9_](字母 + 数字 + 下划线) - 长度限制:6 ~ 18 个字符
- 不允许空格、特殊符号(如
@!#)
REG_PWD.test('pass_123'); // true
REG_PWD.test('UPPER_case_01'); // true
REG_PWD.test('abc'); // false(太短)
REG_PWD.test('pass word'); // false(含空格)
REG_PWD.test('p@ssword'); // false(含 @)如果业务要求密码强制包含大小写 + 数字组合,需在此正则基础上补充额外校验规则。
REG_EMAIL — 邮箱
/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/- 本地部分:
\w+([-+.]\w+)*,支持+、-、.分隔 - 域名部分:
\w+([-.]\w+)*\.\w+([-.]\w+)*,支持子域名和多级后缀 - 校验范围覆盖 99% 的常见邮箱格式
REG_EMAIL.test('user@example.com'); // true
REG_EMAIL.test('user+filter@gmail.com'); // true
REG_EMAIL.test('user.name@sub.domain.io'); // true
REG_EMAIL.test('user@'); // false
REG_EMAIL.test('@example.com'); // false
REG_EMAIL.test('user@example'); // false(无顶级域名)REG_CODE_SIX — 六位数字验证码
/^\d{6}$/精确匹配 6 位连续数字,不多不少。
REG_CODE_SIX.test('123456'); // true
REG_CODE_SIX.test('12345'); // false(5 位)
REG_CODE_SIX.test('1234567'); // false(7 位)
REG_CODE_SIX.test('12345a'); // false(含字母)REG_CODE_FOUR — 四位数字验证码
/^\d{4}$/精确匹配 4 位连续数字,常用于支付密码、短信验证码等场景。
REG_CODE_FOUR.test('1234'); // true
REG_CODE_FOUR.test('0000'); // true
REG_CODE_FOUR.test('123'); // false(3 位)
REG_CODE_FOUR.test('12345'); // false(5 位)REG_URL — HTTP/HTTPS URL
/(((^https?:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)$/- 支持
http://和https://协议 - 支持无协议前缀但以
www.开头的 URL - 支持路径、查询参数、锚点
- 支持用户名@主机格式
REG_URL.test('https://example.com'); // true
REG_URL.test('http://example.com/path?q=1#hash'); // true
REG_URL.test('https://user@example.com:8080'); // true
REG_URL.test('www.example.com'); // true
REG_URL.test('ftp://example.com'); // false(非 http/https)
REG_URL.test('example.com'); // false(无协议无 www)
REG_URL.test('not a url'); // false在表单中使用
原生表单
function validatePhone(value: string): string | null {
if (!REG_PHONE.test(value)) return '请输入正确的手机号';
return null;
}Ant Design Form
<Form.Item
name="phone"
rules={[
{ required: true, message: '请输入手机号' },
{ pattern: REG_PHONE, message: '手机号格式不正确' },
]}
>
<Input placeholder="请输入手机号" />
</Form.Item>React Hook Form
<input
{...register('email', {
required: '请输入邮箱',
pattern: {
value: REG_EMAIL,
message: '邮箱格式不正确',
},
})}
/>Zod schema
import { z } from 'zod';
import { REG_PHONE, REG_EMAIL, REG_PWD } from '@skyroc/utils';
const loginSchema = z.object({
phone: z.string().regex(REG_PHONE, '手机号格式不正确'),
password: z.string().regex(REG_PWD, '密码为 6-18 位字母、数字或下划线'),
});
const registerSchema = z.object({
email: z.string().regex(REG_EMAIL, '邮箱格式不正确'),
username: z.string().regex(REG_USER_NAME, '用户名为 4-16 位,支持中文、英文、数字、_、-'),
verifyCode: z.string().regex(REG_CODE_SIX, '请输入 6 位验证码'),
});关于 g 标志
这些正则不含 g(全局)标志,可以安全地在多次 test() 调用中复用,不会因 lastIndex 状态导致奇怪的行为:
// ✅ 安全,无 g 标志时 lastIndex 始终为 0
REG_PHONE.test('13812345678'); // true
REG_PHONE.test('13812345678'); // true(仍然正确)
// ⚠️ 如果有 g 标志(本模块不存在此问题,仅作示意)
const reg = /^\d+$/g;
reg.test('123'); // true
reg.test('123'); // false(lastIndex 被修改,第二次从 lastIndex 开始匹配)