Skip to content

正则表达式的应用

约 1674 字大约 6 分钟

正则表达式字符串

2025-08-18

一、正则表达式基础

1. 创建正则表达式

在JavaScript中,有两种方式创建正则表达式:

// 字面量形式
const regex1 = /pattern/flags;

// 构造函数形式
const regex2 = new RegExp('pattern', 'flags');

2. 常用修饰符(flags)

  • i: 不区分大小写匹配
  • g: 全局匹配(查找所有匹配而非在第一个匹配后停止)
  • m: 多行匹配
  • u: 使用Unicode码点进行匹配
  • s: 允许.匹配换行符(ES2018新增)

3. 正则表达式方法

3.1 正则对象的方法

const regex = /hello/;

// test() - 测试是否匹配,返回布尔值
regex.test('hello world'); // true

// exec() - 执行搜索匹配,返回结果数组或null
regex.exec('hello world'); // ["hello", index: 0, input: "hello world", groups: undefined]

3.2 字符串的方法

const str = 'hello world';

// match() - 返回匹配结果
str.match(/hello/); // ["hello", index: 0, input: "hello world", groups: undefined]

// search() - 返回匹配到的位置索引
str.search(/world/); // 6

// replace() - 替换匹配的子串
str.replace(/world/, 'JavaScript'); // "hello JavaScript"

// split() - 使用正则分割字符串
str.split(/\s+/); // ["hello", "world"]

二、正则表达式语法

1. 字符类

  • \d: 数字(0-9)
  • \D: 非数字
  • \w: 单词字符(字母、数字、下划线)
  • \W: 非单词字符
  • \s: 空白字符(空格、制表符、换行符等)
  • \S: 非空白字符
  • .: 除换行符外的任意字符(使用s修饰符时可包含换行符)

2. 量词

  • *: 0次或多次
  • +: 1次或多次
  • ?: 0次或1次
  • {n}: 恰好n次
  • {n,}: 至少n次
  • {n,m}: n到m次

3. 边界匹配

  • ^: 字符串开头(多行模式下匹配行开头)
  • $: 字符串结尾(多行模式下匹配行结尾)
  • \b: 单词边界
  • \B: 非单词边界

4. 分组与捕获

  • (...): 捕获分组
  • (?:...): 非捕获分组
  • (?<name>...): 命名捕获组(ES2018)

5. 断言

  • x(?=y): 正向肯定查找(后面是y的x)
  • x(?!y): 正向否定查找(后面不是y的x)
  • (?<=y)x: 反向肯定查找(前面是y的x)(ES2018)
  • (?<!y)x: 反向否定查找(前面不是y的x)(ES2018)

三、常见场景正则表达式示例

1. 邮箱验证

const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

// 测试
emailRegex.test('user@example.com'); // true
emailRegex.test('user.name+tag@example.co.uk'); // true
emailRegex.test('invalid.email@'); // false

2. 手机号验证(中国大陆)

const mobileRegex = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/;

// 测试
mobileRegex.test('13800138000'); // true
mobileRegex.test('+8613800138000'); // true
mobileRegex.test('008613800138000'); // true
mobileRegex.test('12345678901'); // false

3. 身份证号验证(中国大陆)

const idCardRegex = /^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/;

// 测试
idCardRegex.test('110105199003077274'); // true
idCardRegex.test('11010519900307727X'); // true
idCardRegex.test('123456199001011234'); // false

4. URL验证

const urlRegex = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([\/\w .-]*)*\/?$/;

// 测试
urlRegex.test('https://www.example.com/path/to/page'); // true
urlRegex.test('http://example.com'); // true
urlRegex.test('www.example.com'); // false

5. 密码强度验证

// 至少8位,包含大小写字母和数字
const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/;

// 测试
strongPasswordRegex.test('Password1'); // true
strongPasswordRegex.test('password'); // false
strongPasswordRegex.test('PASSWORD1'); // false
strongPasswordRegex.test('Pass1'); // false (长度不足)

6. 日期格式验证(YYYY-MM-DD)

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

// 测试
dateRegex.test('2023-05-15'); // true
dateRegex.test('2023-13-01'); // false
dateRegex.test('2023-02-30'); // false

7. 提取HTML标签中的内容

const htmlRegex = /<([a-z][a-z0-9]*)[^>]*>(.*?)<\/\1>/i;

// 测试
const match = '<div class="content">Hello World</div>'.match(htmlRegex);
console.log(match[2]); // "Hello World"

8. 去除字符串首尾空格

const trimRegex = /^\s+|\s+$/g;

// 测试
'   hello world   '.replace(trimRegex, ''); // "hello world"

9. 匹配中文

const chineseRegex = /[\u4e00-\u9fa5]/;

// 测试
chineseRegex.test('中文'); // true
chineseRegex.test('English'); // false

10. 匹配IPv4地址

const ipv4Regex = /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/;

// 测试
ipv4Regex.test('192.168.1.1'); // true
ipv4Regex.test('256.168.1.1'); // false

11. 匹配金额(保留2位小数)

const moneyRegex = /^\d+(\.\d{1,2})?$/;

// 测试
moneyRegex.test('123.45'); // true
moneyRegex.test('123'); // true
moneyRegex.test('123.456'); // false

12. 匹配HTML注释

const commentRegex = /<!--[\s\S]*?-->/g;

// 测试
'<!-- 这是注释 --><div></div>'.match(commentRegex); // ["<!-- 这是注释 -->"]

13. 匹配Hex颜色值

const colorRegex = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;

// 测试
colorRegex.test('#fff'); // true
colorRegex.test('#FFFFFF'); // true
colorRegex.test('#1234567'); // false

14. 匹配Base64编码

const base64Regex = /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$/;

// 测试
base64Regex.test('SGVsbG8gV29ybGQ='); // true
base64Regex.test('123456'); // false

15. 匹配信用卡号(通用)

const creditCardRegex = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/;

// 测试
creditCardRegex.test('4111111111111111'); // true (Visa)
creditCardRegex.test('5500000000000004'); // true (MasterCard)
creditCardRegex.test('340000000000009'); // true (American Express)

四、实用技巧与最佳实践

  1. 使用命名捕获组提高可读性
const dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = dateRegex.exec('2023-05-15');
console.log(match.groups); // {year: "2023", month: "05", day: "15"}
  1. 动态创建正则表达式
function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

const searchTerm = 'hello.world';
const regex = new RegExp(escapeRegExp(searchTerm), 'gi');
  1. 使用正向/反向断言
// 匹配后面跟着px的数字
const pxRegex = /\d+(?=px)/;
'12px'.match(pxRegex); // ["12"]

// 匹配前面有$的数字
const dollarRegex = /(?<=\$)\d+/;
'Price: $100'.match(dollarRegex); // ["100"]
  1. 性能优化
  • 避免过度使用通配符.*,尽量使用更具体的模式
  • 将最可能匹配的模式放在前面
  • 避免不必要的捕获组,使用非捕获组(?:...)
  • 预编译常用正则表达式(特别是在循环中使用时)
  1. 调试正则表达式

可以使用在线工具如 regex101.comregexr.com 来调试和测试正则表达式。

五、常见问题与解决方案

1. 贪婪匹配 vs 惰性匹配

默认情况下,量词是贪婪的(尽可能多匹配),可以在量词后加?变为惰性匹配(尽可能少匹配)。

const greedyRegex = /<.*>/;
const lazyRegex = /<.*?>/;

'<div>content</div>'.match(greedyRegex)[0]; // "<div>content</div>"
'<div>content</div>'.match(lazyRegex)[0]; // "<div>"

2. 多行匹配

使用m修饰符使^$匹配每行的开头和结尾。

const multiLineRegex = /^line/gm;
const text = `line 1
line 2
line 3`;

text.match(multiLineRegex); // ["line", "line", "line"]

3. Unicode字符匹配

使用u修饰符正确处理Unicode字符。

/^.$/.test('😊'); // false
/^.$/u.test('😊'); // true

4. 替换中的特殊字符

replace方法中使用$&, $1, $2等引用匹配结果。

'John Smith'.replace(/(\w+)\s(\w+)/, '$2, $1'); // "Smith, John"