正则表达式总结

正则表达式总结

一、正则表达式简介

正则表达式(Regular Expression)是一种用于匹配字符串中字符组合的模式,广泛应用于文本处理、数据验证、搜索替换等领域。通过特定的字符和符号组合来定义匹配规则,能够高效地对字符串进行复杂的匹配和操作。

正则表达式引擎会从左到右扫描目标字符串,试图找到与正则表达式模式匹配的文本片段。当找到匹配时,会返回匹配的文本内容或根据指定的操作(如替换)进行处理。

二、基本语法

(一)字符匹配

表达式描述示例及说明
.匹配任意单个字符(除换行符\n外)a.b 可以匹配 a1ba2ba b
[abc]匹配方括号内的任意一个字符[abc] 可以匹配 abc
[a-z]匹配指定范围内的任意一个字符[a-z] 可以匹配任意一个小写字母
[^abc]匹配不在方括号内的任意一个字符[^abc] 可以匹配除 abc 之外的任意字符
\d匹配任意数字,等价于 [0-9]\d 可以匹配 019
\w匹配任意字母或数字或下划线,等价于 [A-Za-z0-9_]\w 可以匹配 aB7_
\s匹配任意空白字符,包括空格、制表符、换页符等\s 可以匹配空格、\t\f
\D匹配任意非数字,等价于 [^0-9]\D 可以匹配 a@#
\W匹配任意非字母数字下划线,等价于 [^A-Za-z0-9_]\W 可以匹配 @#%
\S匹配任意非空白字符\S 可以匹配 a7@

(二)数量匹配

表达式描述示例及说明
*匹配前面的字符或子模式零次或多次a* 可以匹配 ""(空字符串)、aaa
+匹配前面的字符或子模式一次或多次a+ 可以匹配 aaa 等,但不能匹配空字符串
?匹配前面的字符或子模式零次或一次a? 可以匹配 ""(空字符串)或 a
{n}匹配前面的字符或子模式恰好 na{3} 可以匹配 aaa
{n,}匹配前面的字符或子模式至少 na{2,} 可以匹配 aaaaa
{n,m}匹配前面的字符或子模式至少 n 次,最多 ma{1,3} 可以匹配 aaaaaa
*?非贪心匹配,匹配前面的字符或子模式零次或多次,尽可能少地匹配.*? 匹配尽可能少的任意字符
+?非贪心匹配,匹配前面的字符或子模式一次或多次,尽可能少地匹配.+? 匹配尽可能少的一个或多个字符
??非贪心匹配,匹配前面的字符或子模式零次或一次,尽可能少地匹配a?? 匹配尽可能少的零个或一个 a
{n}?非贪心匹配,匹配前面的字符或子模式恰好 na{3}? 匹配 aaa,但会尝试更短的匹配
{n,}?非贪心匹配,匹配前面的字符或子模式至少 n 次,尽可能少地匹配a{2,}? 匹配至少两个 a,但尽可能少
{n,m}?非贪心匹配,匹配前面的字符或子模式至少 n 次,最多 m 次,尽可能少地匹配a{1,3}? 匹配 aaaaaa,但会优先尝试更短的匹配

(三)位置匹配

表达式描述示例及说明
^匹配字符串的开头^a 可以匹配以 a 开头的字符串
$$`匹配字符串的结尾a$$ 可以匹配以a` 结尾的字符串
\b匹配单词边界\bword\b 可以匹配独立的单词 word,但不会匹配 wording 中的 word
\B匹配非单词边界\Bword\B 可以匹配 wording 中的 word,但不会匹配独立的单词 word
^(多行模式)在多行模式下,匹配每一行的开头(?m)^a 可以匹配多行字符串中以 a 开头的每一行
$$`(多行模式)在多行模式下,匹配每一行的结尾(?m)a$$ 可以匹配多行字符串中以a` 结尾的每一行

(四)分组与引用

表达式描述示例及说明
()分组,将多个字符或子模式组合在一起作为一个整体进行匹配和操作(ab)+ 可以匹配 ababab
\1\2引用前面的分组,\1 引用第一个分组,\2 引用第二个分组等(\d+)\.\1 可以匹配 123.123456.456 等,其中 \1 引用了第一个分组 (\d+)
(?:...)非捕获分组,将多个字符或子模式组合在一起,但不进行捕获(?:ab)+ 可以匹配 ababab 等,但不会捕获分组内容
(?=...)正向肯定预查,在匹配的当前位置,确保其后能匹配指定的模式,但不消耗字符(?=\d+) 可以在当前位置后匹配任意数字,但不包括数字本身
(?!...)正向否定预查,在匹配的当前位置,确保其后不能匹配指定的模式,不消耗字符(?!abc) 可以在当前位置后确保不匹配 abc
(?<=...)反向肯定预查,在匹配的当前位置,确保其前能匹配指定的模式,不消耗字符(?<=abc) 可以在当前位置前匹配 abc,但不包括 abc 本身
(?<!...)反向否定预查,在匹配的当前位置,确保其前不能匹配指定的模式,不消耗字符(?<!abc) 可以在当前位置前确保不匹配 abc

三、常见应用场景

(一)验证数据格式

验证内容正则表达式示例及说明
邮件地址^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$匹配常见的电子邮件地址,如 user@example.com
手机号码(中国大陆)^1[3-9]\d{9}$匹配中国大陆手机号码,如 13812345678
身份证号码^\d{15}(\d{2}[0-9xX])?$匹配 15 位或 18 位身份证号码,如 123456789012345678
URL`^(https?ftp)://\s/$.?#.\s*$`匹配常见的 URL,如 http://example.comhttps://example.com/page
IPv4 地址`^(25[0-5]2[0-4]\d1\d{2}[1-9]?\d).(25[0-5]2[0-4]\d1\d{2}[1-9]?\d).(25[0-5]2[0-4]\d1\d{2}[1-9]?\d).(25[0-5]2[0-4]\d1\d{2}[1-9]?\d)$`匹配合法的 IPv4 地址,如 192.168.0.1
日期(YYYY-MM-DD)^\d{4}-\d{2}-\d{2}$匹配日期格式,如 2024-10-01
货币金额^\d+(\.\d{2})?$匹配货币金额,如 123123.45
银行卡号^\d{16,19}$匹配常见的银行卡号,如 1234567890123456
社交安全号码(SSN)`^(?!0006669\d{2})\d{3}-(?!00)\d{2}-(?!0000)\d{4}$`匹配美国 SSN 号码,如 123-45-6789
域名^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$匹配域名,如 example.comsub.domain.co.uk

(二)提取特定信息

提取内容正则表达式示例及说明
HTML 标签内容<[^>]+>([^<]+)</[^>]+>从 HTML 中提取标签内容,如 <p>Hello</p> 提取 Hello
URL 参数[?&]([^=&]+)=([^&]*)从 URL 中提取参数,如 ?page=1&size=10 提取 page=1size=10
日志文件中的时间戳\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}从日志文件中提取时间戳,如 2024-10-01 12:34:56
日志文件中的 IP 地址\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b从日志文件中提取 IP 地址,如 192.168.0.1
文本中的电话号码\d{3}-\d{3}-\d{4}提取电话号码,如 123-456-7890
文本中的日期\b\d{4}-\d{2}-\d{2}\b提取日期,如 2024-10-01
文本中的邮箱地址\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b提取邮箱地址,如 user@example.com
文本中的 URL\bhttps?://[^\s]+提取 URL,如 http://example.com
文本中的信用卡号`\b(?:\d{4}-){3}\d{4}\b\d{16}\b`提取信用卡号,如 1234-5678-9012-34561234567890123456
文本中的价格\b\d+(\.\d{2})?\b提取价格,如 123123.45

(三)替换文本内容

替换内容正则表达式示例及说明
多个空格替换为一个s/\s+/ /g将文本中的多个连续空格替换为一个空格,如 Hello World 替换为 Hello World
日期格式转换s/(\d{4})-(\d{2})-(\d{2})/\3-\2-\1/g将日期格式从 YYYY-MM-DD 替换为 DD-MM-YYYY,如 2024-10-01 替换为 01-10-2024
URL 参数排序s/([&?])([^\s&]+)=([^\s&]+)([&])([^\s&]+)=([^\s&]+)/\1\5=\6\4\2=\3/g对 URL 参数进行排序,如 ?b=2&a=1 替换为 ?a=1&b=2
HTML 标签转换s/<[^>]+>//g去除 HTML 标签,如 <p>Hello</p> 替换为 Hello
转义特殊字符s/([<>&'"/])/\\\$1/g转义 HTML 特殊字符,如 < 替换为 &lt;
标准化电话号码s/(\d{3})-(\d{3})-(\d{4})/(\1) \2-\3/g将电话号码格式标准化,如 123-456-7890 替换为 (123) 456-7890
转换为小写s/[A-Z]/\l&/g将文本转换为小写,如 Hello World 替换为 hello world
转换为大写s/[a-z]/\u&/g将文本转换为大写,如 hello world 替换为 HELLO WORLD
首字母大写`s/(^\s)([a-z])/\1\u\2/g`将每个单词的首字母大写,如 hello world 替换为 Hello World

四、常用修饰符

修饰符描述示例及说明
i忽略大小写/abc/i 匹配 abcAbcABC
g全局匹配,查找所有匹配而非在第一个匹配后停止/abc/g 在字符串中查找所有 abc 匹配
m多行模式,^ 和 $$` 匹配每一行的开头和结尾(?m)^abc$$ 匹配多行字符串中每一行以abc` 开头和结尾的行
s单行模式,. 匹配包括换行符在内的所有字符(?s).+ 匹配包括换行符在内的所有字符
uUnicode 模式,支持 Unicode 字符/abc/u 支持 Unicode 字符匹配
x扩展模式,忽略模式中的空白字符和注释(?x)\d+ # 匹配数字 匹配数字,忽略注释和空白

五、正则表达式工具推荐

(一)在线正则表达式测试工具

工具名称网址特点
Regex101https://regex101.com/支持多种编程语言,提供详细的匹配结果和解释,支持在线调试和修改
正则表达式在线测试https://tool.oschina.net/regex国内工具,支持中文,界面简洁,操作方便
Debuggexhttps://debuggex.com/以可视化的方式展示正则表达式的匹配过程,帮助理解复杂的匹配逻辑
Regexrhttps://regexr.com/提供丰富的示例和教程,支持实时测试和调试,支持多种正则表达式引擎

(二)编程语言中的正则表达式库

编程语言库名称描述
PythonrePython 的内置正则表达式库,功能强大,支持丰富的正则表达式操作
JavaScriptRegExpJavaScript 的内置正则表达式对象,广泛用于前端和 Node.js 开发
Javajava.util.regexJava 的正则表达式库,功能全面,支持复杂的正则表达式操作
PHPpregPHP 的 PCRE(Perl 兼容正则表达式)库,功能强大,广泛用于 Web 开发
C#System.Text.RegularExpressions.NET 的正则表达式库,功能丰富,支持多种正则表达式操作
RubyRegexpRuby 的内置正则表达式库,语法简洁,易于使用

六、正则表达式在不同编程语言中的使用示例

(一)Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import re

# 匹配验证
pattern = r'^\d{3}-\d{3}-\d{4}$'
text = '123-456-7890'
match = re.match(pattern, text)
if match:
print('匹配成功')
else:
print('匹配失败')

# 搜索表
text = 'Hello 123 World 456'
new_text = re.sub(r'\d+', 'NUM', text)
print(new_text) # 输出: Hello NUM World NUM

# 提取信息
text = 'Email: user@example.com, Phone: 123-456-7890'
emails = re.findall(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b', text)
phones = re.findall(r'\d{3}-\d{3}-\d{4}', text)
print(emails) # 输出: ['user@example.com']
print(phones) # 输出: ['123-456-7890']

(二)JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 匹配验证
const pattern = /^\d{3}-\d{3}-\d{4}$/;
const text = '123-456-7890';
if (pattern.test(text)) {
console.log('匹配成功');
} else {
console.log('匹配失败');
}

// 搜索网页
const text = 'Hello 123 World 456';
const new_text = text.replace(/\d+/g, 'NUM');
console.log(new_text); // 输出: Hello NUM World NUM

// 提取信息
const text = 'Email: user@example.com, Phone: 123-456-7890';
const emails = text.match(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g);
const phones = text.match(/\d{3}-\d{3}-\d{4}/g);
console.log(emails); // 输出: ['user@example.com']
console.log(phones); // 输出: ['123-456-7890']

(三)Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.util.regex.*;

public class RegexExample {
public static void main(String[] args) {
// 匹配验证
String pattern = "^\\d{3}-\\d{3}-\\d{4}$";
String text = "123-456-7890";
boolean matches = Pattern.matches(pattern, text);
System.out.println(matches ? "匹配成功" : "匹配失败"); // 输出: 匹配成功

// 替换文本
String text = "Hello 123 World 456";
String new_text = text.replaceAll("\\d+", "NUM");
System.out.println(new_text); // 输出: Hello NUM World NUM

// 提取信息
String text = "Email: user@example.com, Phone: 123-456-7890";
Pattern emailPattern = Pattern.compile("\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b");
Matcher emailMatcher = emailPattern.matcher(text);
while (emailMatcher.find()) {
System.out.println(emailMatcher.group()); // 输出: user@example.com
}

Pattern phonePattern = Pattern.compile("\\d{3}-\\d{3}-\\d{4}");
Matcher phoneMatcher = phonePattern.matcher(text);
while (phoneMatcher.find()) {
System.out.println(phoneMatcher.group()); // 输出: 123-456-7890
}
}
}

七、注意事项

(一)性能问题

  • 避免过度使用正则表达式:正则表达式虽然强大,但过度使用会导致代码可读性下降和性能问题。对于简单的字符串操作,优先考虑使用字符串方法(如 splitreplace 等)。
  • 优化复杂的正则表达式:避免使用过于复杂的模式,尽量使用非捕获分组 ?: 和非贪心匹配来提高性能。
  • 使用预编译:在需要多次使用同一个正则表达式时,提前编译正则表达式可以提高性能,如 Java 中的 Pattern.compile 和 Python 中的 re.compile

(二)特殊字符转义

  • 反斜杠转义:在正则表达式中,一些特殊字符(如 .*+?()[]{}^$\ 等)具有特殊含义,如果需要匹配这些字符本身,需要使用反斜杠 \ 进行转义。例如,要匹配 .,应使用 \.
  • 编程语言中的转义:在某些编程语言中(如 Python、Java 等),反斜杠本身需要转义,因此需要使用双反斜杠 \\。例如,在 Python 中匹配 \d 需要写成 \\d

(三)贪心与非贪心匹配

  • 贪心匹配:默认情况下,正则表达式中的数量匹配符号(如 *+?{n,m} 等)是贪心的,会尽可能多地匹配字符。例如,<.*> 会匹配 <html>...</html> 中的整个字符串。
  • 非贪心匹配:如果需要非贪心匹配,可以在数量匹配符号后添加 ?。例如,<.*?> 会匹配 <html><body> 等尽可能少的字符。

(四)常见问题与解决方法

  • 匹配换行符:默认情况下,. 不匹配换行符 \n。如果需要匹配包括换行符在内的所有字符,可以使用单行模式 s 修饰符。例如,(?s).+ 会匹配包括换行符在内的所有字符。
  • 多行模式匹配:在多行字符串中,如果需要匹配每一行的开头或结尾,可以使用多行模式 m 修饰符。例如,(?m)^abc$ 会匹配多行字符串中每一行以 abc 开头和结尾的行。
  • 处理 Unicode 字符:在处理 Unicode 字符时,确保使用支持 Unicode 的正则表达式库,并添加 u 修饰符。例如,在 JavaScript 中使用 /abc/u 来匹配 Unicode 字符。

八、正则表达式学习资源

(一)书籍

书名作者描述
《正则表达式权威指南》杰夫·弗里德劳全面深入地介绍了正则表达式的原理、语法和应用,适合初学者和进阶读者
《精通正则表达式》杰夫·弗里德劳详细讲解了正则表达式的高级技巧和优化方法,适合有一定基础的读者
《正则表达式 Pocket 参考》杰夫·弗里德劳精简实用的正则表达式参考手册,适合随时查阅

(二)在线教程

网站名称网址特点
MDN Web Docshttps://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions详细的正则表达式教程,涵盖语法、示例和常见应用,适合 JavaScript 开发者
Runoobhttps://www.runoob.com/regexp/regexp-tutorial.html简洁易懂的正则表达式教程,包含丰富的示例和练习,适合初学者
W3Schoolhttps://www.w3schools.com/js/js_regexp.asp提供正则表达式的基础教程和示例,适合快速入门

(三)视频教程

平台名称视频名称特点
Bilibili正则表达式从入门到精通详细的正则表达式讲解,包含大量实例和练习,适合初学者和进阶读者
YouTubeRegular Expressions Tutorial for Beginners由 freeCodeCamp 提供的正则表达式入门教程,内容清晰,适合初学者
UdemyThe Complete Regular Expressions Course全面的正则表达式课程,涵盖基础和高级内容,提供实践项目和练习

九、总结

正则表达式是一种强大的文本处理工具,广泛应用于数据验证、信息提取、文本替换等领域。掌握正则表达式的基本语法和应用场景,可以帮助开发者更高效地处理文本数据。通过不断学习和实践,可以逐渐掌握正则表达式的高级技巧,解决复杂的文本处理问题。

在学习和使用正则表达式时,需要注意性能优化、特殊字符转义、贪心与非贪心匹配等问题。利用在线工具和学习资源,可以更轻松地理解和掌握正则表达式的使用方法。