JavaScript 正则表达式:基本匹配与捕获组
正则表达式是处理文本的强大工具。在JavaScript中,正则表达式可用于搜索、替换和提取文本。本文将介绍正则表达式的基本匹配规则和捕获组的用法。
基本匹配规则
创建 正则表达式有两种方式:使用字面量或构造函数。
// 字面量方式
const regex1 = /pattern/flags;
// 构造函数方式
const regex2 = new RegExp('pattern', 'flags');
1. 字符匹配
匹配 特定字符是最简单的正则表达式形式。
// 匹配字母a
const regex = /a/;
console.log(regex.test('apple')); // true
console.log(regex.test('banana')); // true
console.log(regex.test('cherry')); // false
使用 元字符可以匹配更复杂的模式。
| 元字符 | 描述 | 示例 |
|---|---|---|
. |
匹配除换行外的任何字符 | /a.c/ 匹配 "abc", "aac" |
\d |
匹配数字(0-9) | /\d/ 匹配 "1", "5" |
\w |
匹配字母、数字和下划线 | /\w/ 匹配 "a", "1", "_" |
\s |
匹配空白字符 | /\s/ 匹配 " ", "\t", "\n" |
\b |
匹配单词边界 | /\bcat\b/ 匹配 "cat" 但不匹配 "category" |
2. 字符类
定义 字符类可以匹配一组字符中的任何一个。
// 匹配a或b
const regex = /[ab]/;
console.log(regex.test('apple')); // true
console.log(regex.test('banana')); // true
console.log(regex.test('cherry')); // false
// 匹配a-z的任何字母
const regex2 = /[a-z]/;
console.log(regex2.test('apple')); // true
console.log(regex2.test('123')); // false
使用 取反字符类匹配不在指定集中的字符。
// 匹配非数字字符
const regex = /[^0-9]/;
console.log(regex.test('a123')); // true
console.log(regex.test('123')); // false
3. 量词
指定 前面的元素可以出现多少次。
| 量词 | 描述 | 示例 |
|---|---|---|
* |
匹配0次或多次 | /a*/ 匹配 "", "a", "aaa" |
+ |
匹配1次或多次 | /a+/ 匹配 "a", "aaa" 但不匹配 "" |
? |
匹配0次或1次 | /a?/ 匹配 "", "a" |
{n} |
匹配恰好n次 | /a{3}/ 匹配 "aaa" |
{n,} |
匹配至少n次 | /a{2,}/ 匹配 "aa", "aaa" |
{n,m} |
匹配n到m次 | /a{2,4}/ 匹配 "aa", "aaa", "aaaa" |
// 匹配3个数字
const regex = /\d{3}/;
console.log(regex.test('123')); // true
console.log(regex.test('1234')); // true
console.log(regex.test('12')); // false
4. 锚点
指定 匹配必须出现在字符串的特定位置。
| 锚点 | 描述 | 示例 |
|---|---|---|
^ |
匹配字符串开头 | /^apple/ 匹配 "apple pie" 但不匹配 "pineapple" |
$` | 匹配字符串结尾 | `/apple$/ 匹配 "big apple" 但不匹配 "apple pie" |
||
\b |
匹配单词边界 | /\bcat\b/ 匹配 "cat" 但不匹配 "category" |
// 验证邮箱格式
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
console.log(emailRegex.test('user@example.com')); // true
console.log(emailRegex.test('invalid.email')); // false
```
---
## 捕获组
**捕获组** 允许你从匹配的字符串中提取特定部分。使用括号 `()` 创建捕获组。
### 1. 基本捕获组
**创建** 基本捕获组来匹配和捕获子字符串。
```javascript
const str = '2023-10-15';
const regex = /(\d{4})-(\d{2})-(\d{2})/;
const match = str.match(regex);
console.log(match);
// 输出: ["2023-10-15", "2023", "10", "15", index: 0, input: "2023-10-15", groups: undefined]
```
**访问** 捕获组内容:
```javascript
// 完整匹配
console.log(match[0]); // "2023-10-15"
// 第一个捕获组
console.log(match[1]); // "2023"
// 第二个捕获组
console.log(match[2]); // "10"
// 第三个捕获组
console.log(match[3]); // "15"
```
### 2. 命名捕获组
**使用** `?<name>` 语法为捕获组命名,使代码更易读。
```javascript
const str = '2023-10-15';
const regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = str.match(regex);
console.log(match.groups.year); // "2023"
console.log(match.groups.month); // "10"
console.log(match.groups.day); // "15"
```
### 3. 非捕获组
**使用** `(?:)` 创建非捕获组,只匹配但不捕获内容。
```javascript
const str = 'apple, banana, cherry';
const regex = /(?:apple|banana| cherry), (pear|orange)/;
const match = str.match(regex);
console.log(match);
// 输出: ["cherry, orange", "orange", index: 14, input: "apple, banana, cherry", groups: undefined]
// 非捕获组内容不会被捕获
console.log(match[1]); // "orange" (捕获的内容)
// 非捕获组 "apple|banana| cherry" 不会出现在结果中
```
### 4. 反向引用
**引用** 前面的捕获组来匹配相同的文本。
```javascript
// 匹配重复的单词
const regex = /(\w+)\s+\1/;
console.log(regex.test('hello hello')); // true
console.log(regex.test('hello world')); // false
// 在替换中使用反向引用
const str = 'apple banana apple';
const newStr = str.replace(/(\w+)\s+(\w+)\s+(\w+)/, '$3 $2 $1');
console.log(newStr); // "apple banana apple" 变为 "apple banana apple"
实用示例
1. 表单验证
验证 电话号码格式。
// 美国电话号码格式: (123) 456-7890
const phoneRegex = /^\(\d{3}\) \d{3}-\d{4}$/;
const phoneNumber = '(123) 456-7890';
console.log(phoneRegex.test(phoneNumber)); // true
```
**验证** 密码强度(至少8个字符,包含大小写字母和数字)。
```javascript
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;
console.log(passwordRegex.test('Weak')); // false
console.log(passwordRegex.test('StrongPass123')); // true
2. 文本处理
提取 文章中的所有URL。
const text = '访问 https://example.com 获取更多信息,或联系 mail@example.com。';
const urlRegex = /(https?:\/\/[^\s]+)/;
const urls = text.match(urlRegex);
console.log(urls[0]); // "https://example.com"
替换 文本中的特定模式。
const text = 'Hello, I am 30 years old.';
const newAge = '31';
const newText = text.replace(/I am \d+ years old/, `I am ${newAge} years old`);
console.log(newText); // "Hello, I am 31 years old."
```
### 3. 数据提取
**解析** 日志文件中的时间戳。
```javascript
const logEntry = '[2023-10-15 14:30:45] ERROR: Connection failed';
const regex = /ZGJLJSMATHTOKEN0X (\w+): (.*)/;
const match = logEntry.match(regex);
const timestamp = match[1];
const level = match[2];
const message = match[3];
console.log(`时间: ${timestamp}, 级别: ${level}, 消息: ${message}`);
// 输出: "时间: 2023-10-15 14:30:45, 级别: ERROR, 消息: Connection failed"
提取 HTML标签中的属性。
const html = '<a href="https://example.com" target="_blank">链接</a>';
const attrRegex = /<a\s+([^>]+)>/;
const match = html.match(attrRegex);
console.log(match[1]); // "href="https://example.com" target="_blank""
优化 性能的正则表达式。
// 避免使用贪婪量词导致回溯
const regex = /^a+$/; // 匹配一个或多个a
const str = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
console.log(regex.test(str)); // 高效匹配
```
### 4. 高级技巧
**使用** `RegExp` 对象的 `exec` 方法进行迭代匹配。
```javascript
const text = 'apple banana orange apple';
const regex = /\w+/;
let match;
while ((match = regex.exec(text)) !== null) {
console.log(`找到单词: ${match[0]},位置: ${match.index}`);
}
使用 正则表达式的 sticky 标志进行连续匹配。
const text = 'abc123abc456abc';
const regex = /abc\d*/y; // y标志表示粘性匹配
regex.lastIndex = 3; // 从位置3开始
console.log(regex.exec(text)); // ["abc123", index: 3, input: "abc123abc456abc", groups: undefined]
regex.lastIndex = 9; // 从位置9开始
console.log(regex.exec(text)); // ["abc456", index: 9, input: "abc123abc456abc", groups: undefined]
正则表达式工具
使用 在线正则表达式测试工具验证和调试你的模式。
# 推荐工具
- regex101.com
- regexr.com
- regexper.com
参考 Mozilla开发者网络(MDN)获取完整的正则表达式文档。
# MDN文档
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
学习 以下资源加深对正则表达式的理解。
# 书籍推荐
- 《精通正则表达式》(Jeffrey E.F. Friedl)
- 《正则表达式必知必会》(Ben Forta)
实践 编写正则表达式解决实际问题是最好的学习方式。

暂无评论,快来抢沙发吧!