Python正则表达式,正则表达式 (regex) 是特殊的字符序列,用于查找或匹配字符串中的模式,正如本正则表达式简介所解释的那样。我们之前已经展示了如何在JavaScript和PHP中使用正则表达式。本文的重点是 Python 正则表达式,旨在帮助您更好地理解如何在 Python 中操作正则表达式。
Python 中的正则表达式模块:re 和 regex
Python 有两个模块 –re
和regex
– 有助于使用正则表达式。该re
模块内置于 Python 中,而该regex
模块由 Matthew Barnett 开发,可在PyPI上使用。Barnett的regex
模块是使用内置re
模块开发的,两个模块具有相似的功能。它们在实施方面有所不同。内置re
模块是两者中更受欢迎的,所以我们将在这里使用该模块。
Python 的内置 re 模块
通常情况下,Python 开发人员re
在执行正则表达式时会使用该模块。正则表达式语法的一般构造保持不变(字符和符号),但该模块提供了一些函数和方法来在 Python 程序中有效地执行正则表达式。
在我们可以使用该re
模块之前,我们必须像任何其他 Python 模块或库一样将它导入我们的文件:
import re
这使得该模块在当前文件中可用,以便可以轻松访问 Python 的正则表达式函数和方法。使用该re
模块,我们可以创建 Python regex 对象,操作匹配的对象,并在必要时应用标志。
重新函数的选择。
该re
模块具有 、 和 等功能re.search()
,re.match()
我们re.compile()
将首先讨论这些功能。
re.search(模式,字符串,标志= 0)与re.match(模式,字符串,标志= 0)
re.search()
并在re.match()
字符串中搜索 Python 正则表达式模式,如果找到或未找到None
匹配对象,则返回匹配项。
这两个函数总是返回在给定字符串中找到的第一个匹配的子字符串,并保持0
标志的默认值。但是,虽然该search()
函数会扫描整个字符串以查找匹配项,match()
但只会在字符串的开头搜索匹配项。
Python 的re.search()
文档:
扫描字符串寻找正则表达式模式产生匹配的第一个位置,并返回相应的匹配对象。
None
如果字符串中没有位置与模式匹配则返回;请注意,这与在字符串中的某个点查找零长度匹配不同。
Python 的re.match()
文档:
如果string开头的零个或多个字符与正则表达式pattern匹配,则返回相应的匹配对象。
None
如果字符串与模式不匹配则返回;请注意,这与零长度匹配不同。
让我们看一些代码示例以进一步阐明:
search_result = [re.search](http://re.search)(r'\d{2}', 'I live at 22 Garden Road, East Legon') print(search_result) print(search_result.group()) >>>> <re.Match object; span=(10, 12), match='22'> 22
match_result = re.match(r'\d{2}', 'I live at 22 Garden Road, East Legon') print(match_result) print(match_result.group()) >>>> None Traceback (most recent call last): File "/home/ini/Dev./sitepoint/regex.py", line 4, in <module> print(match_result.group()) AttributeError: 'NoneType' object has no attribute 'group'
在上面的例子中,None
因为在字符串的开头没有匹配而被返回。AttributeError
调用方法时引发了an group()
,因为没有匹配对象:
atch_result = re.match(r'\d{2}', "45 cars were used for the president's convoy") print(match_result) print(match_result.group()) >>>> <re.Match object; span=(0, 2), match='45'> 45
对于字符串开头的匹配对象 45,该match()
方法工作正常。
重新编译(模式,标志=0)
该compile()
函数采用给定的正则表达式模式并将其编译为用于在字符串或文本中查找匹配项的正则表达式对象。它还接受 aflag
作为可选的第二个参数。此方法很有用,因为可以将 regex 对象分配给变量并稍后在我们的 Python 代码中使用。r"..."
在创建 Python 正则表达式对象时,请始终记住使用原始字符串。
这是它如何工作的示例:
regex_object = re.compile(r'b[ae]t') mo = regex_object.search('I bet, you would not let a bat be your president') print(regex_object) >>>> re.compile('b[ae]t')
re.fullmatch(模式,字符串,标志= 0)
此函数有两个参数:一个作为正则表达式模式传递的字符串、一个要搜索的字符串和一个可选的标志参数。如果整个字符串匹配给定的正则表达式模式,则返回一个匹配对象。如果没有匹配项,则返回None
:
regex_object = re.compile(r'Tech is the future') mo = regex_object.fullmatch('Tech is the future, join now') print(mo) print([mo.group](http://mo.group)()) >>>> None Traceback (most recent call last): File "/home/ini/Dev./sitepoint/regex.py", line 16, in <module> print([mo.group](http://mo.group)()) AttributeError: 'NoneType' object has no attribute 'group'
代码引发AttributeError
, 因为没有字符串匹配。
re.findall(模式,字符串,标志= 0)
该findall()
函数返回在给定字符串中找到的所有匹配对象的列表。它从左到右遍历字符串,直到返回所有匹配项。请参阅下面的代码片段:
regex_object = re.compile(r'[A-Z]\w+') mo = regex_object.findall('Pick out all the Words that Begin with a Capital letter') print(mo) >>>> ['Pick', 'Words', 'Begin', 'Capital']
在上面的代码片段中,正则表达式由一个字符类和一个单词字符组成,以确保匹配的子字符串以大写字母开头。
re.sub(模式,repl,字符串,计数=0,标志=0)
借助该sub()
函数,可以将字符串的一部分替换为另一个子字符串。它至少需要三个参数:搜索模式、替换字符串和要处理的字符串。如果未找到匹配项,则返回原始字符串不变。在不传递计数参数的情况下,该函数默认会查找一次或多次出现的正则表达式并替换所有匹配项。
这是一个例子:
regex_object = re.compile(r'disagreed') mo = regex_object.sub('agreed',"The founder and the CEO disagreed on the company's new direction, the investors disagreed too.") print(mo) >>>> The founder and the CEO agreed on the company's new direction, the investors agreed too.
subn(模式,repl,字符串,计数=0,标志=0)
该subn()
函数执行与 相同的操作sub()
,但它返回一个元组,其中包含已完成的字符串和替换次数。请参阅下面的代码片段:
regex_object = re.compile(r'disagreed') mo = regex_object.subn('agreed',"The founder and the CEO disagreed on the company's new direction, the investors disagreed too.") print(mo) >>>> ("The founder and the CEO agreed on the company's new direction, the investors agreed too.", 2)
匹配对象和方法
当正则表达式模式与正则表达式对象的or方法中的给定字符串匹配时,将返回匹配对象。Match 对象有几种方法,在 Python 中操纵正则表达式时证明是有用的。search()
match()
Match.group([group1, …])
此方法返回匹配对象的一个或多个子组。单个参数将返回一个信号子组;多个参数将根据它们的索引返回多个子组。默认情况下,该group()
方法返回整个匹配子字符串。当 中的参数group()
大于或小于子组时,IndexError
抛出异常。
这是一个例子:
regex_object = re.compile(r'(\+\d{3}) (\d{2} \d{3} \d{4})') mo = regex_object.search('Pick out the country code from the phone number: +233 54 502 9074') print([mo.group](http://mo.group)(1)) >>>> +233
1
传递到方法中的参数group(1)
——如上例所示——挑选出 Ghana 的国家代码+233
。调用不带参数或0
作为参数的方法将返回匹配对象的所有子组:
regex_object = re.compile(r'(\+\d{3}) (\d{2} \d{3} \d{4})') mo = regex_object.search('Pick out the phone number: +233 54 502 9074') print([mo.group](http://mo.group)()) >>>> +233 54 502 9074
匹配组(默认=无)
groups()
返回与给定字符串匹配的子组元组。正则表达式模式组总是用括号捕获 — ()
— 当匹配时,这些组将作为元组中的元素返回:
regex_object = re.compile(r'(\+\d{3}) (\d{2}) (\d{3}) (\d{4})') mo = regex_object.search('Pick out the phone number: +233 54 502 9074') print(mo.groups()) >>>> ('+233', '54', '502', '9074')
Match.start([group]) & Match.end([group])
该start()
方法返回开始索引,而该end()
方法返回匹配对象的结束索引:
regex_object = re.compile(r'\s\w+') mo = regex_object.search('Match any word after a space') print('Match begins at', mo.start(), 'and ends', mo.end()) print([mo.group](http://mo.group)()) >>>> Match begins at 5 and ends 9 any
上面的示例有一个正则表达式模式,用于匹配空格后的任何单词字符。找到匹配项——' any'
从位置 5 开始,到 9 结束。
Pattern.search(string[, pos[, endpos]])
该pos
值指示应开始搜索匹配对象的索引位置。endpos
指示搜索匹配项应停止的位置。pos
和的值都endpos
可以在字符串后的search()
或方法中作为参数传递。match()
它是这样工作的:
regex_object = re.compile(r'[a-z]+[0-9]') mo = regex_object.search('find the alphanumeric character python3 in the string', 20 , 30) print([mo.group](http://mo.group)()) >>>> python3
上面的代码挑选出搜索字符串中的任何字母数字字符。
搜索从字符串索引位置 20 开始,到 30 停止。
重新正则表达式标志
Python 允许在使用诸如and之类的模块方法时使用标志,这为正则表达式提供了更多上下文。这些标志是可选参数,用于指定 Python 正则表达式引擎如何查找匹配对象。re
search()
match()
re.I (re.IGNORECASE)
在执行区分大小写的匹配时使用此标志。正则表达式引擎将忽略正则表达式模式的大写或小写变体:
regex_object = [re.search](http://re.search)('django', 'My tech stack comprises of python, Django, MySQL, AWS, React', re.I) print(regex_object.group()) >>>> Django
确保找到匹配对象,re.I
无论它是大写还是小写。
re.S (re.DOTALL)
'.'
特殊字符匹配除换行符以外的任何字符。引入此标志还将匹配文本块或字符串中的换行符。请参见下面的示例:
regex_object= [re.search](http://re.search)('.+', 'What is your favourite coffee flavor \nI prefer the Mocha') print(regex_object.group()) >>>> What is your favourite coffee flavor
该'.'
字符只从字符串的开头找到匹配项并在换行符处停止。引入re.DOTALL
标志将匹配换行符。请参见下面的示例:
regex_object= [re.search](http://re.search)('.+', 'What is your favourite coffee flavor \nI prefer the Mocha', re.S) print(regex_object.group()) >>>> What is your favourite coffee flavor I prefer the Mocha
re.M (re.MULTILINE)
默认情况下,'^'
特殊字符仅匹配字符串的开头。引入此标志后,该函数会在每行的开头搜索匹配项。该'$'
字符仅匹配字符串末尾的模式。但是该re.M
标志确保它还在每行的末尾找到匹配项:
regex_object = [re.search](http://re.search)('^J\w+', 'Popular programming languages in 2022: \nPython \nJavaScript \nJava \nRust \nRuby', re.M) print(regex_object.group()) >>>> JavaScript
re.X (re.VERBOSE)
有时,Python 正则表达式模式会变得又长又乱。re.X
当我们需要在正则表达式模式中添加注释时,该标志会有所帮助。我们可以使用'''
字符串格式来创建带有注释的多行正则表达式:
email_regex = [re.search](http://re.search)(r''' [a-zA-Z0-9._%+-]+ # username composed of alphanumeric characters @ # @ symbol [a-zA-Z0-9.-]+ # domain name has word characters (\.[a-zA-Z]{2,4}) # dot-something ''', 'extract the email address in this string [kwekujohnson1@gmail.com](mailto:kwekujohnson1@gmail.com) and send an email', re.X) print(email_regex.group()) >>>> [kwekujohnson1@gmail.com](mailto:kwekujohnson1@gmail.com)
Python 正则表达式的实际例子
现在让我们深入研究一些更实际的例子。
Python密码强度测试正则表达式
正则表达式最流行的用例之一是测试密码强度。注册任何新帐户时,都会进行检查以确保我们输入适当的字母、数字和字符组合,以确保密码安全。
这是用于检查密码强度的示例正则表达式模式:
password_regex = re.match(r""" ^(?=.*?[A-Z]) # this ensures user inputs at least one uppercase letter (?=.*?[a-z]) # this ensures user inputs at least one lowercase letter (?=.*?[0-9]) # this ensures user inputs at least one digit (?=.*?[#?!@$%^&*-]) # this ensures user inputs one special character .{8,}$ #this ensures that password is at least 8 characters long """, '@Sit3po1nt', re.X) print('Your password is' ,password_regex.group()) >>>> Your password is @Sit3po1nt
注意使用'^'
和'$'
以确保输入字符串(密码)是正则表达式匹配。
Python在文件正则表达式中搜索和替换
这是这个例子的目标:
- 创建文件“pangram.txt”。
- 在文件中添加一些简单的文本,
"The five boxing wizards climb quickly."
- 编写一个简单的 Python 正则表达式来搜索并将“climb”替换为“jump”,这样我们就有了一个 pangram。
这是执行此操作的一些代码:
#importing the regex module import re file_path="pangram.txt" text="climb" subs="jump" #defining the replace method def search_and_replace(filePath, text, subs, flags=0): with open(file_path, "r+") as file: #read the file contents file_contents = [file.read](http://file.read)() text_pattern = re.compile(re.escape(text), flags) file_contents = text_pattern.sub(subs, file_contents) [file.seek](http://file.seek)(0) file.truncate() file.write(file_contents) #calling the search_and_replace method search_and_replace(file_path, text, subs)
Python 网络抓取正则表达式
有时您可能需要在 Internet 上收集一些数据或自动执行简单的任务,例如网络抓取。在线提取某些数据时,正则表达式非常有用。下面是一个例子:
import urllib.request phone_number_regex = r'\(\d{3}\) \d{3}-\d{4}' url = 'https://www.summet.com/dmsi/html/codesamples/addresses.html' # get response response = urllib.request.urlopen(url) # convert response to string string_object = [response.read](http://response.read)().decode("utf8") # use regex to extract phone numbers regex_object = re.compile(phone_regex) mo = regex_object.findall(string_object) # print top 5 phone numbers print(mo[: 5]) >>>> ['(257) 563-7401', '(372) 587-2335', '(786) 713-8616', '(793) 151-6230', '(492) 709-6392']
结论
正则表达式可以从简单到复杂变化。正如上面的示例所示,它们是编程的重要组成部分。为了更好地理解 Python 中的正则表达式,最好先熟悉字符类、特殊字符、锚点和分组结构等内容。
我们可以进一步加深对 Python 中正则表达式的理解。Pythonre
模块可以更轻松地快速启动和运行。
正则表达式显着减少了我们需要编写的代码量来执行诸如验证输入和实施搜索算法之类的事情。
能够回答有关正则表达式使用的问题也很好,因为它们经常出现在软件工程师和开发人员的技术面试中。