Python正则表达式揭秘:用Python的re模块解读模式匹配的艺术
![掌握Python正则表达式:深入研究模式匹配 四海 第1张-四海吧 Image created by the author on Canva](https://miro.medium.com/v2/resize:fit:640/format:webp/1*Fezh62ZWutqEQtOTHRfOFQ.png)
什么是Python正则表达式或正则表达式?
正则表达式通常被缩写为regex,是处理文本的强大工具。本质上,它们由一系列字符组成,用于建立搜索的模式。这个模式可以用于广泛的字符串操作,包括匹配模式、替换文本和分割字符串。
正则表达式的历史
数学家Stephen Cole Kleene在20世纪50年代首次引入了正则表达式,作为描述正则集合或正则语言的符号。
如今,正则表达式已经成为程序员、数据科学家和IT专业人士的重要技能。
Python正则表达式的重要性和用途
在深入了解如何使用Python来使用这些正则表达式之前,让我们先看看它的应用范围,以激发我们的动力。
- 数据验证:正则表达式可以非常有用地验证不同类型的数据(如电子邮件地址、电话号码)。
- 网页抓取:在通过网页抓取数据时,可以使用正则表达式解析HTML并隔离所需的信息。
- 搜索和替换:正则表达式擅长识别符合特定模式的字符串,并用替代内容进行替换。这种能力在文本编辑器、数据库和编码中特别有价值。
- 语法高亮:许多文本编辑器使用正则表达式进行语法高亮。
- 自然语言处理(NLP):在NLP中,正则表达式可用于词法分析、词干提取和其他一系列文本处理功能。
- 日志分析:在处理日志文件时,正则表达式可以有效地提取特定的日志条目或分析一段时间内的模式。
现在我希望你已经有了足够的动力!
让我们开始使用re模块,它完全关于正则表达式。
开始使用Python的re模块
太好了,让我们从Python的re模块基础知识开始。在接下来的几节中,我们将涵盖更高级的话题。
re模块简介
Python通过re模块提供了对正则表达式的内在支持。
该模块是Python的标准库,这意味着您不需要外部安装,它将随每个Python安装一起提供。
re模块包含各种用于处理正则表达式的函数和类。其中一些函数用于匹配文本,一些用于分割文本,其他用于替换文本。
它包含了一系列专为处理正则表达式而设计的函数和类。其中一些函数用于文本匹配,其他函数用于文本分割或文本替换。
导入re模块
如前所述,它随安装而来,所以不需要担心安装问题。
因此,要在Python中开始使用正则表达式,您需要首先导入re库。您可以通过以下导入语句来完成这一点。
import re
在导入库之后,您可以开始使用re模块提供的功能,如函数和类。
让我们从一个简单的例子开始。
假设您想在字符串中找到所有出现的单词“Python”。
我们可以使用re模块中的findall()函数。
这是代码。
import re # 示例文本 text = "Python是一种令人惊叹的编程语言。Python广泛应用于各个领域。" # 查找所有出现的'Python' matches = re.findall("Python", text) # 输出匹配结果 print(matches)
这是输出结果。
re模块中还有许多其他函数,我们可以使用它们来构建更复杂的模式。
但是首先,让我们看一下re模块中的常用函数。
re模块中的常用函数
在向您介绍Python正则表达式的基础知识之前,让我们先看一下常用函数,以更好地理解剩余的概念。re模块包含许多不同的函数。通过使用它们,我们可以执行不同的操作。
在接下来的部分中,我们将发现其中的一些函数。
a. re.match() 函数
re.match() 函数用于检测正则表达式是否从字符串的开头开始匹配。
如果匹配成功,函数返回一个匹配的对象;如果匹配失败,函数返回None。
接下来,我们将使用re.match()函数。在这里,我们将检查字符串text是否以单词“Python”开头。然后,我们将将结果打印到控制台。
这是代码。
import re pattern = "Python" text = "Python是令人惊叹的。" # 检查文本是否以'Python'开头 match = re.match(pattern, text) # 输出结果 if match: print("找到匹配项:", match.group()) else: print("未找到匹配项")
这是输出结果。
输出结果显示,模式“Python”与文本的开头匹配。
b. re.search() 函数
与re.match()相反,re.search()函数在字符串的整个范围内搜索匹配项,如果找到匹配项,则返回一个匹配的对象。
在下面的代码中,我们使用re.search()函数在字符串text中搜索单词“amazing”。如果找到该单词,我们打印它;否则,我们打印“未找到匹配项”。
这是代码。
pattern = "amazing" text = "Python是令人惊叹的。" # 在文本中搜索模式 match = re.search(pattern, text) # 输出结果 if match: print("找到匹配项:", match.group()) else: print("未找到匹配项")
这是输出结果。
输出结果显示,我们的代码从给定的文本中捕获了amazing。
c. re.findall() 函数
re.findall()函数用于在字符串中收集模式的所有非重叠匹配项,并将这些匹配项作为字符串列表返回。
在下面的示例中,我们使用re.findall()函数查找字符串中的所有“a”。匹配项以列表形式返回,然后我们将其打印到控制台。
这是代码。
pattern = "a" text = "这是一个示例文本。" # 查找文本中所有出现的'a' matches = re.findall(pattern, text) # 输出匹配项 print(matches)
这是输出结果。
输出表示在我们的文本中找到的所有不重叠的“a”字母的出现。
d. re.finditer() 函数
re.finditer() 函数类似于 re.findall(),但它返回一个迭代器,该迭代器产生匹配对象。
在下面的代码中,使用 re.finditer() 函数在字符串文本中找到所有“a”字母的出现。它返回一个匹配对象的迭代器,我们打印每个匹配的索引和值。
以下是代码。
pattern = "a"text = "这是一个示例文本。"# 在文本中找到所有出现的 'a'matches = re.finditer(pattern, text)# 输出匹配for match in matches: print(f"在索引 {match.start()} 处找到匹配项:{match.group()}")
以下是输出。
输出显示了在文本中的模式“a”的索引。
e. re.sub() 函数
re.sub() 函数用于将一个字符串替换为另一个字符串。
接下来,我们将使用 re.sub() 函数将“Python”替换为“Java”。
然后,我们打印修改后的字符串。
以下是代码。
pattern = "Python"replacement = "Java"text = "我喜欢 Python。Python 真棒。"# 将 'Python' 替换为 'Java'new_text = re.sub(pattern, replacement, text)# 输出新的字符串print(new_text) # 输出:"我喜欢 Java。Java 真棒。"
以下是输出。
输出显示我们可以成功地将文本中的“Python”替换为“Java”。
在下一节中,我们将介绍正则表达式中可以用于匹配各种文本模式的基本模式。
Python 正则表达式中的基本模式
让我们从基本模式开始。
正则表达式通过字面字符、元字符和量词的组合构建而成。因此,掌握这些基本组件对于创建有效的正则表达式很重要。
让我们从字面字符开始。
a. 字面字符
字面字符是正则表达式中最简单的模式匹配形式。
它们完全匹配它们自身,没有特殊含义。
例如,正则表达式 python 将精确匹配字符串 python。
import re pattern = "python"text = "我喜欢编程使用 python!" # 在文本中找到所有出现的 'Python'matches = re.findall(pattern, text) # 输出匹配print(matches)
以下是输出。
输出显示我们的 re.findall() 函数找到了所有的模式“python”的实例。
b. 元字符
元字符像“.”、“^”、“$”这样的字符对于操作字符串非常重要。让我们来看看。
i. 点 (.)
点 . 就像是个百搭卡。它可以代替除换行符以外的任意单个字符。
在下面的代码中,我们将使用一个正则表达式模式“p.t”。
以下是代码。
import re pattern = "p.t"text = "pat, pet, p5t, 但不是 pt." # 在文本中找到所有出现的 'Python'matches = re.findall(pattern, text) # 输出匹配print(matches)
以下是输出。
输出显示我们的代码找到了所有以“p”开头并以“t”结尾的三个字符实例。
ii. 插入符号 (^)
插入符号 ^ 用于检查字符串是否以某个字符开头。
让我们看一个例子。
以下代码检查文本是否以 Hello 开头(匹配结果为 “match”)或者不是(未找到匹配)
以下是代码。
import repattern = "^Hello"text = "Hello, world!"# 使用 re.match() 函数因为它只在字符串开始位置进行匹配match = re.match(pattern, text)# 输出匹配结果if match: print("匹配成功:", match.group())else: print("未找到匹配")
以下是输出结果。
输出结果显示我们的代码捕捉到了文本开头的 hello 模式。
iii. 美元符号 ($)
美元符号 $ 用于检查字符串是否以某个字符结尾。
以下代码检查文本是否以 world 结尾(如果是则打印 “匹配成功:”match),或者不是(如果不是则打印 “未找到匹配”)
以下是代码。
import repattern = "world$"text = "Hello, world"# 使用 re.search() 函数搜索整个字符串match = re.search(pattern, text)# 输出匹配结果if match: print("匹配成功:", match.group()) # 输出: 匹配成功: worldele: print("未找到匹配")
以下是输出结果。
输出结果显示 re.search() 函数找到了以单词 “world” 结尾的文本。
c. 量词
量词用于定义在模式匹配中字符(或字符)应出现的次数。
在本小节中,我们将以星号(*)为例,接着讲解加号(+),然后是问号(?),最后是花括号({})。
让我们从星号开始。
i. 星号 (*)
正则表达式中的星号 (*) 表示前一个字符可以出现零次或多次。
让我们看看代码。在下面的代码中,我们首先定义了模式(”py”),然后使用 findall() 函数。
以下是代码。
import repattern = "py*"text = "p py pyy pyyy pyyyy"matches = re.findall(pattern, text)print(matches)
以下是输出结果。
输出结果显示所有的匹配,因为星号允许 “y” 出现零次或多次。
ii. 加号 (+)
加号 + 匹配前一个字符的重复次数至少为 1 次。
这里我们再次使用 findall() 函数与模式 “py”,但这次我们使用加号(+)。
以下是代码。
import repattern = "py+"text = "p py pyy pyyy pyyyy"matches = re.findall(pattern, text)print(matches) # 输出: ['py', 'pyy', 'pyyy', 'pyyy']
以下是输出结果。
从输出结果可以看出,加号要求 “p” 后至少有一个或多个 “y”。
iii. 问号(?)
问号 ? 匹配前一个字符出现 0 次或 1 次。它使前一个字符变为可选。
以下是代码。
import repattern = "py?"text = "p py pyy pyyy pyyyy"matches = re.findall(pattern, text)print(matches) # 输出: ['p', 'py', 'p', 'p', 'p']
这里是输出结果。
在输出结果中,您可以看到它只匹配了“p”和“py”,因为问号允许出现“y”零次或一次。
iv. 大括号({})
大括号{}允许您匹配特定数量的重复。
import repattern = "py{2,3}"text = "py, pyy, pyyy, pyyyy"matches = re.findall(pattern, text)print(matches) # 输出:['pyy', 'pyyy', 'pyy']
这里是输出结果。
在这个例子中,模式匹配了“pyy”和“pyyy”,但不匹配“py”或“pyyyy”,因为我们指定了在“p”之后要精确匹配2或3个“y”字符。
Python正则表达式中的特殊字符
特殊字符可以用来构建更复杂的模式。
a. 字符类
首先让我们看看字符类。
在以下示例中,我们将看到其中的3个。
让我们从\d、\D开始。
i. \d、\D
“\d”用于查找数字(从0到9),相反,“\D”用于查找非数字元素。
在以下代码中,“\d”扫描文本字符串并从文本中检索数字。
import repattern = "\d"text = "我的电话号码是123-456-7890。"# 在文本中查找所有数字matches = re.findall(pattern, text)# 输出匹配的结果print(matches)
这里是输出结果。
输出结果显示我们在文本中找到了所有的数字(0-9)。
ii. \s、\S
“\s”可用于查找空白字符,相反,“\S”可用于查找任何非空白字符。
在下面的示例中,正则表达式“\s”识别给定文本中的所有空格和制表符。
以下是代码。
import repattern = "\s"text = "这是一个带有空格和制表符的文本。"# 在文本中查找所有空白字符matches = re.findall(pattern, text)# 输出匹配的结果print(matches) # 输出:[' ', ' ', ' ', ' ', ' ', ' ', '\t']
这里是输出结果。
从输出结果中可以看出,我们可以识别所有的空白字符。
iii. \w、\W
“\w”可用于查找单词(字母、数字和下划线字符),“\W”与之相反。
在下面的代码中,“\w”从文本中检索所有的字母和数字。
以下是代码。
import repattern = "\w"text = "这是一个带有字母和数字的示例123!"# 在文本中查找所有的字母和数字matches = re.findall(pattern, text)# 输出匹配的结果print(matches)
这里是输出结果。
b. 预定义字符类
预定义字符类提供了常见类的快捷方式。例如,“\d”是一个表示数字的预定义字符类。
在这种情况下,“\d”模式从给定的文本中提取所有数字。
import repattern = "\d"text = "The year is 2023."# 在文本中找到所有数字matches = re.findall(pattern, text)# 输出匹配项print(matches)
这是输出。
输出显示我们的代码已经找到了文本中所有预定义字符类“\d”(表示所有数字)的实例。
c. 自定义字符类
自定义字符类允许您使用方括号 [] 定义自己的字符集。
在下面的示例中,自定义字符类“[aeiou]”用于在文本中查找所有元音字母。
这是代码。
import repattern = "[aeiou]"text = "This is an example text."# 在文本中找到所有元音matches = re.findall(pattern, text)# 输出匹配项print(matches)
这是输出。
输出显示所有我们定义的文本中的元音的实例。
我们还可以使用“-”来定义字符的范围。
这是代码。
pattern = "[A-Z]"text = "This is an Example Text With Uppercase Letters."# 在文本中找到所有大写字母matches = re.findall(pattern, text)# 输出匹配项print(matches)
这是输出。
这里输出包含了文本中的大写字母。
编译 Python 正则表达式
当您在脚本中多次使用相同的正则表达式时,将其编译为模式对象可以节省时间。这样做可以节省大量时间,因为不需要每次使用时都重新解析正则表达式。
a. compile() 方法
re.compile() 方法可用于将正则表达式模式编译为模式对象。
一旦我们有了这个模式对象,我们可以调用它的方法(匹配文本、搜索和其他操作)。
这是代码。
import re# 编译正则表达式模式pattern = re.compile(r'\d+') # 匹配一个或多个数字# 使用模式对象搜索匹配项text = "There are 3 apples and 4 oranges."matches = pattern.findall(text)# 输出匹配项print(matches)
这是输出。
输出显示数字。
b. 编译正则表达式的好处
以下是使用正则表达式的一些好处:
- 性能:它更快,特别是如果正则表达式将被多次使用。
- 可重用性:一旦编译,相同的模式对象可以在代码的不同部分中多次重用。
- 可读性:使用模式对象可以使您的代码更清晰,特别是当使用复杂的正则表达式时。
这是编译正则表达式的简单示例:
import re# 编译正则表达式模式pattern = re.compile(r'\d+') # 匹配一个或多个数字# 在不同的文本中使用模式对象寻找匹配项text1 = "There are 3 apples."text2 = "I have 15 dollars and 30 cents."# 在文本1中查找匹配项matches1 = pattern.findall(text1)# 在文本2中查找匹配项matches2 = pattern.findall(text2)# 输出匹配项print(matches1)
这里是输出。
现在我们来检查第二段文字。
这里是代码。
print(matches2)
这里是输出。
我们上面的示例对于您掌握可重用性、性能和可读性的重要性来说还是相当简单的,特别是当我们的模式计划重复使用时。
实际示例:提取电话号码
在本节中,让我们通过编写一个Python脚本来从文本中提取电话号码来测试我们一起发现的内容。
这是正则表达式的常见用法,特别是在数据清理过程中。
a. 定义正则表达式模式
电话号码可以采用不同的格式,特别是在不同的国家,所以您可以根据自己的情况调整这些号码,对于本例,让我们考虑格式XXX-XXX-XXXX,其中X是一个数字。
以下代码定义了一个与上述格式匹配并符合此模式的正则表达式模式。
让我们看看代码。
import re# 定义电话号码的正则表达式模式phone_number_pattern = re.compile(r'\d{3}-\d{3}-\d{4}')
b. 使用findall()方法
在这个例子中,我们将使用findall()方法来提取与我们的模式匹配的电话号码。
以下代码使用正则表达式模式来查找和提取所有的
import re# 定义电话号码的正则表达式模式phone_number_pattern = re.compile(r'\d{3}-\d{3}-\d{4}')# 包含电话号码的示例文本text = """John Doe: 123-456-7890Jane Doe: 234-567-8901Office: 555-555-5555"""# 在文本中查找所有的电话号码phone_numbers = phone_number_pattern.findall(text)
c. 打印结果
最后,让我们将提取的电话号码打印到控制台。
以下是代码。
# 输出电话号码print("找到的电话号码:")for phone_number in phone_numbers: print(phone_number)
这里是输出。
d. 完整的示例代码
以下是结合了上述所有步骤的完整Python脚本:
import re# 定义电话号码的正则表达式模式phone_number_pattern = re.compile(r'\d{3}-\d{3}-\d{4}')# 包含电话号码的示例文本text = """John Doe: 123-456-7890Jane Doe: 234-567-8901Office: 555-555-5555"""# 在文本中查找所有的电话号码phone_numbers = phone_number_pattern.findall(text)# 输出电话号码print("找到的电话号码:")for phone_number in phone_numbers: print(phone_number)
这里是输出。
最佳实践
在您继续使用正则表达式时,请记住以下几个最佳实践:
- 保持简单:简单是关键。通常建议使用较简单的模式,因为正则表达式可能会立即变得复杂。
- 为模式添加注释:在为项目开发正则表达式时,请不要忘记在注释中加入注释,因为正如我们所说的,它可能会变得复杂,但一旦您在回顾时这样做了,您的代码将可重用。
- 彻底测试:反复测试您的代码,因为正则表达式有时可能会产生意外结果,这是由于它们的复杂性,因此彻底测试将确保您的工作按预期运行。
- 使用原始字符串:在使用Python处理文本时,有时会使用具有不同含义的特殊字符(如反斜杠\是或\n表示换行)。为了避免混淆,Python允许您使用所谓的“原始字符串”。您只需在字符串的第一个引号之前加上字母“r”,即可使字符串成为“原始”字符串。当这样做时,Python会理解该字符串中的反斜杠应该被视为普通字符,而不是特殊字符。
结论
在本指南中,我们探索了Python正则表达式的领域。我们从常见的函数和基础知识开始,然后深入了解更高级的概念和实际示例。但请记住,在做实际项目时,这将作为你职业生涯中加深对这一理解的一个例子。只需这样做,您就可以积累知识,避免在处理Python正则表达式时频繁搜索。
请查看这份综合指南,了解高级Python概念的概述。
我希望您通过阅读本文也获得了有价值的关于Python正则表达式的信息。
感谢阅读!
原文发布于https://www.stratascratch.com。