正则表达式(Regular Expression,简称 regex)是一种强大的文本匹配和处理工具,用于在字符串中查找、替换或提取特定模式。以下是正则表达式的主要规则和语法:


1. 基本字符匹配

  • 普通字符:直接匹配自身。例如,a 匹配字符 a
  • 特殊字符:需要转义,例如 .*+?^$()[]{}|\ 等。
    • 例如,\. 匹配字符 .

2. 字符类

  • **[]**:匹配括号内的任意一个字符。
    • 例如,[abc] 匹配 abc
  • **[^]**:匹配不在括号内的任意一个字符。
    • 例如,[^abc] 匹配非 abc 的字符。
  • 范围[a-z] 匹配小写字母,[0-9] 匹配数字。
    • 例如,[a-zA-Z0-9] 匹配任意字母或数字。

3. 预定义字符类

  • **.**:匹配任意单个字符(除了换行符 \n)。
  • **\d**:匹配数字,等价于 [0-9]
  • **\D**:匹配非数字,等价于 [^0-9]
  • **\w**:匹配单词字符(字母、数字、下划线),等价于 [a-zA-Z0-9_]
  • **\W**:匹配非单词字符,等价于 [^a-zA-Z0-9_]
  • **\s**:匹配空白字符(空格、制表符、换行符等)。
  • **\S**:匹配非空白字符。

4. 量词

  • *****:匹配前面的字符 0 次或多次。
    • 例如,a* 匹配 aaaaaa 或空字符串。
  • **+**:匹配前面的字符 1 次或多次。
    • 例如,a+ 匹配 aaaaaa 等。
  • **?**:匹配前面的字符 0 次或 1 次。
    • 例如,a? 匹配 a 或空字符串。
  • **{n}**:匹配前面的字符恰好 n 次。
    • 例如,a{3} 匹配 aaa
  • **{n,}**:匹配前面的字符至少 n 次。
    • 例如,a{2,} 匹配 aaaaa 等。
  • **{n,m}**:匹配前面的字符至少 n 次,至多 m 次。
    • 例如,a{2,4} 匹配 aaaaaaaaa

5. 边界匹配

  • **^**:匹配字符串的开头。
    • 例如,^a 匹配以 a 开头的字符串。
  • **$**:匹配字符串的结尾。
    • 例如,a$ 匹配以 a 结尾的字符串。
  • **\b**:匹配单词边界。
    • 例如,\bword\b 匹配独立的单词 word
  • **\B**:匹配非单词边界。

6. 分组和捕获

  • **()**:将多个字符组合成一个整体,并捕获匹配的内容。
    • 例如,(abc)+ 匹配 abcabcabc 等。
  • **(?:)**:非捕获分组,匹配但不捕获内容。
    • 例如,(?:abc)+ 匹配 abcabcabc 等,但不捕获。

7. 选择符

  • **|**:匹配左边或右边的表达式。
    • 例如,a|b 匹配 ab

8. 贪婪与非贪婪匹配

  • 贪婪匹配:默认情况下,量词会尽可能多地匹配字符。
    • 例如,a.*b 匹配 ab 之间的所有字符。
  • 非贪婪匹配:在量词后加 ?,尽可能少地匹配字符。
    • 例如,a.*?b 匹配 ab 之间的最短内容。

9. 转义字符

  • **\**:用于转义特殊字符。
    • 例如,\. 匹配字符 .\* 匹配字符 *

10. 标志(修饰符)

  • **i**:忽略大小写。
    • 例如,/a/i 匹配 aA
  • **g**:全局匹配,查找所有匹配项。
    • 例如,/a/g 匹配字符串中所有的 a
  • **m**:多行模式,^$ 匹配每行的开头和结尾。
    • 例如,/^a/m 匹配每行以 a 开头的内容。

11. 零宽断言

  • **(?=)**:正向先行断言,匹配后面满足条件的位置。
    • 例如,a(?=b) 匹配后面是 ba
  • **(?!)**:负向先行断言,匹配后面不满足条件的位置。
    • 例如,a(?!b) 匹配后面不是 ba
  • **(?<=)**:正向后行断言,匹配前面满足条件的位置。
    • 例如,(?<=a)b 匹配前面是 ab
  • **(?<!)**:负向后行断言,匹配前面不满足条件的位置。
    • 例如,(?<!a)b 匹配前面不是 ab

12. 其他

  • **\n**:匹配换行符。
  • **\t**:匹配制表符。
  • **\x**:匹配十六进制字符。
    • 例如,\x41 匹配字符 A
  • **\u**:匹配 Unicode 字符。
    • 例如,\u0041 匹配字符 A

示例

  1. 匹配邮箱地址

    1
    /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
  2. 匹配 URL

    1
    /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w\.-]*)*\/?$/
  3. 匹配日期(YYYY-MM-DD)

    1
    /^\d{4}-\d{2}-\d{2}$/

正则表达式的规则非常丰富,掌握这些基本规则后,可以根据实际需求灵活组合使用。
要多次匹配字符串中的所有键值对(如 name=Johnage=25city=New York),可以使用正则表达式的 g 标志(全局匹配),并结合循环或 matchAll 方法。以下是实现方式:


方法 1:使用 matchg 标志

1
2
3
4
5
6
7
8
9
10
var a = /[^=;\s]+=([^=;]+)(?:;?)/g; // 添加 g 标志
var str = "name=John; age=25; city=New York";
var matches = str.match(a);

if (matches) {
for (var i = 0; i < matches.length; i++) {
var match = matches[i].match(/[^=;\s]+=([^=;]+)(?:;?)/);
console.log(match[1]); // 输出: John, 25, New York
}
}

说明

  1. match 方法会返回所有匹配的键值对(如 name=John, age=25, city=New York)。
  2. 然后对每个键值对再次使用正则表达式提取值部分。

方法 2:使用 matchAll

matchAll 方法可以直接返回所有匹配的详细信息,包括捕获组。

1
2
3
4
5
6
7
var a = /[^=;\s]+=([^=;]+)(?:;?)/g; // 添加 g 标志
var str = "name=John; age=25; city=New York";
var matches = str.matchAll(a);

for (var match of matches) {
console.log(match[1]); // 输出: John, 25, New York
}

说明

  1. matchAll 返回一个迭代器,每次迭代返回一个匹配结果。
  2. match[1] 是捕获组的值部分。

方法 3:使用 exec 和循环

exec 方法可以重复调用,每次返回一个匹配结果。

1
2
3
4
5
6
7
var a = /[^=;\s]+=([^=;]+)(?:;?)/g; // 添加 g 标志
var str = "name=John; age=25; city=New York";
var match;

while ((match = a.exec(str)) !== null) {
console.log(match[1]); // 输出: John, 25, New York
}

说明

  1. exec 方法每次调用返回一个匹配结果,直到没有更多匹配。
  2. match[1] 是捕获组的值部分。

输出结果

以上三种方法的输出结果均为:

1
2
3
John
25
New York

总结

  • 使用 g 标志可以实现全局匹配。
  • match 适合简单的多次匹配。
  • matchAllexec 更适合需要捕获组信息的场景。
  • 根据需求选择合适的方法即可。