一、正则表达式基础概念
正则表达式(Regular Expression,简写为 regex、regexp 或 RE),是通过单个字符串描述、匹配一系列符合特定句法规则的字符串搜索模式,核心作用是实现文本搜索与文本替换。
- 本质:由字符序列构成的搜索模式,可简单(如单个字符)可复杂(如多规则组合)。
- JS 中创建方式:
- 字面量形式:
var reg = /pattern/modifiers;
(常用,性能更优) - RegExp 构造函数:
var reg = new RegExp("pattern", "modifiers");
(动态生成正则时使用)
- 字面量形式:
二、正则表达式的核心构成
正则表达式由 定界符、元字符、模式修饰符、表达式 四部分组成,四者协同定义匹配规则。
1. 定界符
用于包裹正则表达式的 “边界符号”,JS 中最常用 正斜线 /
,格式为 /表达式/修饰符
。
- 示例:
/\w+/g
(/
是定界符,\w+
是表达式,g
是修饰符) - 说明:定界符仅用于标记正则的开始与结束,不参与实际匹配。
2. 元字符:正则的 “规则核心”
元字符是具有特殊含义的字符,用于定义匹配规则,分为四大类:原子筛选方式、原子集合、原子数量限定、边界控制。
(1)原子的筛选方式
通过特定符号定义 “匹配哪些单个原子(字符 / 字符组)”,核心是 “选什么”。
筛选符号 | 含义描述 | 示例 | |||
---|---|---|---|---|---|
` | ` | 二选一,匹配 “ | ” 前后任意一项 | `/e | r/g` 匹配字符串中的 “e” 或 “r” |
[] | 匹配方括号内任意一个原子 | /[27]/g 匹配 “2” 或 “7” | |||
[^] | 匹配 “除方括号内原子外” 的任意字符 | /[^0-9]/g 匹配非数字字符 | |||
- | 范围连接符(仅在 [] 内生效),匹配范围两端的字符及中间所有字符 | /[5-9]/g 匹配 5-9 的数字;/[a-zA-Z]/g 匹配所有大小写字母 | |||
() | 模式单元,将括号内的多个原子视为 “一个整体原子” | /(lo)/g 匹配完整的 “lo”,而非单独的 “l” 或 “o” |
示例代码:
var str = 'h2ATel?#9lo27 _w5or7ld';
console.log(str.match(/[a-zA-Z0-9_]/g)); // 匹配数字、字母、下划线
console.log(str.match(/[^abcdefghij]/g)); // 匹配除 a-j 外的所有字符
console.log(str.match(/2|lo/g)); // 匹配 "2" 或 "lo"
(2)原子的集合(预定义字符类)
为常用的 “字符范围” 提供简写,简化正则书写,核心是 “快速选一类”。
预定义符号 | 含义描述 | 等价写法 | 示例 |
---|---|---|---|
. | 匹配除换行符(\n )、回车符(\r )外的任意单个字符 | [^\n\r] | /h./g 匹配 “h” 后面跟任意一个字符(如 “h2”“he”) |
\d | 匹配任意数字 | [0-9] | /\d/g 匹配字符串中所有数字 |
\D | 匹配任意非数字 | [^0-9] | /\D/g 匹配字符串中所有非数字 |
\s | 匹配任意空白字符(空格、制表符 \t 、换行 \n 等) | [\f\n\r\t\v ] | /\s/g 匹配字符串中的所有空格 |
\S | 匹配任意非空白字符 | [^\f\n\r\t\v ] | /\S/g 匹配字符串中的所有非空格 |
\w | 匹配数字、大小写字母、下划线 | [0-9a-zA-Z_] | /\w/g 匹配字符串中的数字、字母、下划线 |
\W | 匹配非数字、非字母、非下划线 | [^0-9a-zA-Z_] | /\W/g 匹配字符串中的特殊符号(如 “?”“#”) |
注意:匹配特殊字符(如 /
、.
、:
)时,需用反斜杠 \
转义(如 \/
匹配 /
,\.
匹配 .
)。
示例代码:
var str = "he12341llo21 world562 http://789455ww78w.baidu.com3";
console.log(str.match(/\/|\./g)); // 匹配 "/" 或 "."
console.log(str.match(/\d/g)); // 匹配所有数字
console.log(str.match(/\w/g)); // 匹配所有数字、字母、下划线
(3)原子数量限定(量词)
定义 “某个原子 / 原子组连续出现的次数”,核心是 “选多少个”。
量词符号 | 含义描述 | 等价写法 | 示例 |
---|---|---|---|
{n} | 匹配前面的原子恰好 n 次 | - | /\d{3}/g 匹配连续 3 个数字(如 “123”“455”) |
{n,} | 匹配前面的原子至少 n 次 | - | /\d{2,}/g 匹配连续 2 个及以上数字(如 “21”“562”) |
{n,m} | 匹配前面的原子n 到 m 次(包含 n 和 m) | - | /\d{2,5}/g 匹配连续 2-5 个数字(如 “12”“78945”) |
+ | 匹配前面的原子至少 1 次 | {1,} | /\d+/g 匹配 1 个及以上数字(等价于 /\d{1,}/g ) |
* | 匹配前面的原子0 次或多次 | {0,} | /\d*/g 匹配 0 个或多个数字(空字符也会匹配) |
? | 匹配前面的原子0 次或 1 次(可选) | {0,1} | /\d?/g 匹配 0 个或 1 个数字 |
关键概念:贪婪匹配 vs 非贪婪匹配
- 贪婪匹配(默认):尽可能匹配最长的符合规则的字符串,如
/^a.+c/
匹配 “apcdefc” 中的 “apcdefc”(从 a 到最后一个 c)。 - 非贪婪匹配(惰性匹配):尽可能匹配最短的符合规则的字符串,在量词后加
?
启用,如/^a.+?c/
匹配 “apcdefc” 中的 “apc”(从 a 到第一个 c)。
示例代码:
var str = "he12341llo21 world562";
console.log(str.match(/\d{3}/g)); // 匹配连续 3 个数字(如 "123")
console.log(str.match(/\d+/g)); // 匹配 1 个及以上数字(如 "12341" "21")
var str2 = 'apcdefc';
console.log(str2.match(/^a.+c/)); // 贪婪匹配:["apcdefc"]
console.log(str2.match(/^a.+?c/)); // 非贪婪匹配:["apc"]
(4)边界控制
定义 “匹配的位置边界”,核心是 “在哪里匹配”。
边界符号 | 含义描述 | 示例 |
---|---|---|
^ | 匹配字符串的开头(多行模式下匹配每行开头) | /^he/g 匹配以 “he” 开头的字符串(如 “hello” 中的 “he”) |
$ | 匹配字符串的结尾(多行模式下匹配每行结尾) | /ld$/g 匹配以 “ld” 结尾的字符串(如 “world” 中的 “ld”) |
\b | 匹配单词边界(单词与非单词的分隔处,如空格、符号) | /\bis/g 匹配 “This is an island” 中的 “is”(独立单词) |
\B | 匹配非单词边界(单词内部的字符间隔) | /is\B/g 匹配 “island” 中的 “is”(非独立单词) |
示例代码:
// 需求:必须以字母开头,后面只能是数字、字母、下划线
var reg = /^[a-zA-Z]\w*$/;
var str = 'w345234sdf';
console.log(reg.test(str)); // true(符合规则)
var str2 = "This is an island";
console.log(str2.search(/\bis/)); // 4(匹配独立的 "is",索引为 4)
console.log(str2.search(/is\b/)); // 4(同上,匹配独立 "is" 的结尾)
console.log(str2.search(/\Bis/)); // 11(匹配 "island" 中的 "is",索引为 11)
3. 模式修饰符
用于修改正则的匹配行为,写在定界符 //
之后,常用修饰符如下:
修饰符 | 含义描述 | 示例 |
---|---|---|
i | 不区分大小写匹配 | /[a-z]/gi 匹配所有字母(无论大小写) |
g | 全局匹配(找到所有匹配项,而非找到第一个就停止) | /l/g 匹配 “hello” 中的两个 “l” |
m | 多行匹配(使 ^ 匹配每行开头,$ 匹配每行结尾) | /^he/gm 匹配 “hello world\nhello jack” 中的两个 “he”(每行开头的 “he”) |
示例代码:
var str = 'ywr9yh3rhyFRE91h';
console.log(str.match(/[a-z]/g)); // 仅匹配小写字母(如 "y" "w")
console.log(str.match(/[a-z]/gi)); // 不区分大小写,匹配所有字母(如 "y" "F" "R")
var str2 = 'hello world \nhello jack';
console.log(str2.match(/^he/g)); // 仅匹配第一行开头的 "he":["he"]
console.log(str2.match(/^he/gm)); // 多行匹配,匹配两行开头的 "he":["he", "he"]
三、JS 中常用正则场景示例
以下是开发中高频使用的正则表达式,可直接参考或调整:
验证场景 | 正则表达式 | 说明 | ||||
---|---|---|---|---|---|---|
非空验证 | /^\S+$/ | 不能全是空白字符(空格、换行等) | ||||
邮箱验证 | /^[\w-]+@([\w-]+\.)+[a-zA-Z0-9]+$/ | 支持常见邮箱格式(如 786087136@qq.com 、ran_yi-hang@163.com.cn ) | ||||
手机号验证 | /^1[356789]\d{9}$/ | 匹配中国大陆手机号(11 位,开头为 13/15/16/17/18/19) | ||||
URL 验证 | /^https?\:\/\/([\w-]+\.)+\S+$/ | 匹配 HTTP/HTTPS 协议的 URL(如 http://www.baidu.com 、https://www.jd.com.cn?name=jack ) | ||||
汉字验证 | /^[\u4e00-\u9fa5]+$/ | 仅匹配纯汉字(单个汉字用 /[\u4e00-\u9fa5]/ ) | ||||
日期格式(yyyy-mm-dd) | `/^[1-9]\d{3}-(0[1-9] | 1[0-2])-(0[1-9] | 1[0-9] | 2[0-9] | 3[0-1])$/` | 匹配合法日期(如 2024-05-20 ,避免 2024-13-32 这类无效日期) |
身份证号码 | /^\d{15}(\d{2}[0-9X])?$/ | 匹配 15 位或 18 位身份证(18 位末位支持 X) | ||||
用户名(字母开头,含字母 / 数字 / 下划线) | /^[a-zA-Z]\w{5,15}$/ | 6-16 位,以字母开头,后续可跟数字、字母、下划线 |
四、JS 中常用正则方法
正则表达式需结合 JS 方法才能实现具体功能,常用方法分为 “字符串方法” 和 “RegExp 对象方法”:
方法类型 | 方法名 | 功能描述 | 示例 |
---|---|---|---|
字符串方法 | str.match(reg) | 查找所有匹配项,返回数组(无匹配则返回 null) | "hello".match(/l/g) → ["l", "l"] |
字符串方法 | str.search(reg) | 查找第一个匹配项的索引(无匹配则返回 -1) | "This is it".search(/is/) → 2 |
字符串方法 | str.replace(reg, replacement) | 替换匹配项,返回新字符串 | "hello".replace(/l/g, "x") → "hexxo" |
字符串方法 | str.split(reg) | 按匹配项拆分字符串,返回数组 | "a1b2c".split(/\d/) → ["a", "b", "c"] |
RegExp 方法 | reg.test(str) | 检测字符串是否匹配,返回布尔值(true/false) | /^1[3-9]\d{9}$/.test("13800138000") → true |
RegExp 方法 | reg.exec(str) | 查找单个匹配项,返回详细信息数组(无匹配则返回 null) | /l/g.exec("hello") → ["l", index: 2, input: "hello"] |