python正则表达式通过re模块实现文本匹配与处理,1.常用函数包括re.search()查找首个匹配、re.match()从开头匹配、re.findall()获取所有匹配、re.sub()替换匹配内容、re.compile()预编译模式提升效率;2.核心语法涵盖通配符、量词、字符集、分组、转义等,支持复杂模式构建;3.高级技巧包括贪婪与非贪婪控制、分组捕获与非捕获、匹配标志应用如忽略大小写和多行模式;4.性能优化需预编译正则、避免灾难性回溯;5.常见陷阱涉及原始字符串缺失、match与search混淆、字符集内元字符误解;6.适用场景为模式匹配、结构化数据提取、动态替换等复杂文本处理,而简单操作优先使用字符串方法。

Python的正则表达式,说白了,就是一套用来描述和匹配字符串模式的强大工具。它通过一套特殊的字符序列(也就是“正则模式”)来查找、替换或提取文本中符合特定规则的内容。在Python里,我们主要通过内置的
re

要用好Python的正则表达式,核心在于理解
re
首先,你需要导入
re
import re
立即学习“Python免费学习笔记(深入)”;

最常用的几个函数:
re.search(pattern, string, flags=0)
pattern
None
findall

text = "我的电话是138-0000-1234,工作电话是010-87654321。"
# 查找手机号
match = re.search(r'\d{3}-\d{4}-\d{4}', text)
if match:
print(f"找到手机号: {match.group()}") # 输出:找到手机号: 138-0000-1234re.match(pattern, string, flags=0)
search
match
text1 = "Hello World" text2 = "World Hello" print(re.match(r'Hello', text1)) # <re.Match object; span=(0, 5), match='Hello'> print(re.match(r'Hello', text2)) # None
re.findall(pattern, string, flags=0)
pattern
text = "电子邮件地址有:test@example.com 和 info@domain.org。"
emails = re.findall(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', text)
print(f"找到的邮箱: {emails}")
# 输出:找到的邮箱: ['test@example.com', 'info@domain.org']re.sub(pattern, repl, string, count=0, flags=0)
pattern
repl
count
text = "我喜欢苹果,也喜欢香蕉,还喜欢苹果。"
new_text = re.sub(r'苹果', '橘子', text)
print(f"替换后: {new_text}") # 输出:替换后: 我喜欢橘子,也喜欢香蕉,还喜欢橘子。re.compile(pattern, flags=0)
re.compile()
search
findall
phone_pattern = re.compile(r'\d{3}-\d{4}-\d{4}')
text1 = "我的电话是138-0000-1234。"
text2 = "联系方式是139-1111-2222。"
print(phone_pattern.search(text1).group())
print(phone_pattern.search(text2).group())一些常用的正则语法元素:
.
+
?
[]
[abc]
[0-9]
()
|
cat|dog
^
$
\
\.
\d
[0-9]
\w
[A-Za-z0-9_]
\s
\b
记住,在Python中使用正则表达式时,最好使用原始字符串(raw string),即在字符串前加
r
r'\d+'
说实话,高级技巧这东西,很多时候就是把基础元素玩出花来。我个人觉得,真正能提升你正则功力的,除了熟练运用基本语法,就是理解一些更微妙的概念和功能了。
一个很有用的概念是贪婪与非贪婪匹配。默认情况下,量词(如
*
+
?
{m,n}?
比如,你想从
<p>这是一个段落</p><p>这是另一个段落</p>
<p>...</p>
r'<p>.*</p>'
这是一个段落</p><p>这是另一个段落</p>
.*
</p>
r'<p>.*?</p>'
.*?
</p>
这是一个段落</p>
?
另一个我觉得挺实用的是分组与捕获。用括号
()
group(index)
date_str = "2023-10-26"
match = re.search(r'(\d{4})-(\d{2})-(\d{2})', date_str)
if match:
year = match.group(1) # 2023
month = match.group(2) # 10
day = match.group(3) # 26
print(f"年: {year}, 月: {month}, 日: {day}")有时候你只想分组,但不想捕获内容,可以使用非捕获分组
(?:...)
还有就是正则表达式的标志(Flags)。
re
re.IGNORECASE
re.I
re.MULTILINE
re.M
^
$
re.DOTALL
re.S
.
text_multiline = "第一行\n第二行" # 默认情况下,. 不匹配换行符 print(re.search(r'.+', text_multiline).group()) # 第一行 # 使用 re.DOTALL,. 匹配换行符 print(re.search(r'.+', text_multiline, re.DOTALL).group()) # 第一行\n第二行
这些高级应用,其实就是对基本概念的灵活组合和对细节的把握。我发现很多人一开始会觉得这些概念有点绕,但一旦理解了,文本处理能力会提升一大截,能解决很多以前觉得无从下手的问题。
谈到性能和陷阱,这真是个老生常谈但又不得不提的话题。我记得有一次,一个简单的正则就让程序卡死了好几秒,后来才发现是贪婪匹配惹的祸。
性能优化方面:
一个很重要的点是预编译正则表达式。如果你需要在一个程序中多次使用同一个正则表达式模式,强烈建议使用
re.compile()
# 不推荐,每次调用都会重新编译
for _ in range(10000):
re.search(r'\d+', 'abc123def')
# 推荐,只编译一次
compiled_pattern = re.compile(r'\d+')
for _ in range(10000):
compiled_pattern.search('abc123def')虽然对于简单的模式和少量操作,差异不明显,但在处理大量文本或复杂模式时,性能提升是显而易见的。
另一个需要注意的,是避免“灾难性回溯”(Catastrophic Backtracking)。这通常发生在模式中包含嵌套的量词,并且这些量词可以匹配空字符串或者重叠匹配时。比如
(a+)+
(a|aa)+
*?
+?
常见陷阱:
忘记使用原始字符串(Raw Strings):前面提过,
r''
'\n'
r'\n'
re.match()
re.search()
re.match()
None
match
search
贪婪与非贪婪的误解:这绝对是初学者最常踩的坑。我上面已经详细解释了,这里就不再赘述了。但记住,当你发现匹配结果比你预期的长时,多半就是贪婪匹配在作祟。
字符集 []
[]
.
*
+
?
|
(
)
{^
$
\
]
]
[foo]
r'\[foo\]'
[.
编码问题:当处理非ASCII字符(比如中文)时,确保你的字符串和正则表达式模式的编码是一致的。Python 3 默认处理Unicode字符串,通常问题不大,但如果你从文件读取数据,或者涉及到不同编码的系统交互,就得注意了。
总的来说,写正则就像写代码,需要测试和调试。当结果不符预期时,不要急着改代码,先仔细检查你的正则表达式,甚至可以利用在线的正则测试工具来逐步调试。
这是一个非常实用的问题,我个人在实际工作中也经常面临这样的选择。我的经验是,如果一个任务能用简单的字符串方法解决,就尽量不用正则。 正则虽然强大,但它的可读性确实比普通字符串方法差一些,而且写起来也更容易出错。
什么时候应该用普通的字符串方法?
in
str.find()
str.index()
str.replace()
text = "Hello World"
if "World" in text: # 简单的查找
print("Found World")
new_text = text.replace("World", "Python") # 简单的替换str.startswith()
str.endswith()
^
$
filename = "report.txt"
if filename.endswith(".txt"):
print("这是一个文本文件")str.split()
data = "apple,banana,orange"
fruits = data.split(',')str.lower()
str.upper()
str.strip()
什么时候应该用正则表达式?
# 查找所有形如 "YYYY-MM-DD" 的日期
text = "项目启动日期是2023-10-26,截止日期是2024-01-15。"
dates = re.findall(r'\d{4}-\d{2}-\d{2}', text)re.sub()
# 将 "姓 名" 格式改为 "名 姓" name = "张 三" new_name = re.sub(r'(\S+)\s+(\S+)', r'\2 \1', name) # \1 \2 引用捕获组 print(new_name) # 三 张
很多时候,两者还会结合使用。比如,你可能先用
str.splitlines()
我的建议是,从最简单的方法开始考虑。如果
str
以上就是Python正则表达式怎么用?文本匹配技巧的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号