Python 正则表达式

正则表达式(Regular Expression),通常简称为正则或RegExp,是一种强大的文本处理工具,用于匹配、查找和替换字符串中的文本模式。Python 使用内置的 re 模块来支持正则表达式操作。在本教程中,您将了解RegEx并了解各种正则表达式。

import re

pattern = r"Hello"
text = "Hello, World!"
result = re.match(pattern, text)

if result:
    print("Match found:", result.group())
else:
    print("Match not found")

输出:

Match found: Hello

在开始使用 Python 正则表达式模块之前,让我们看看如何使用元字符或特殊序列实际编写正则表达式。

元字符

为了理解 RE 类比,元字符非常有用、重要,并且将在模块 re 的函数中使用。以下是元字符列表。

元字符含义
.匹配任何字符,除了换行符 \n
*匹配前一个字符或表达式的零次或多次重复。
+匹配前一个字符或表达式的一次或多次重复。
?匹配前一个字符或表达式的零次或一次重复。
^匹配字符串的开始。
$匹配字符串的结束。
[]定义字符类,匹配其中任何一个字符。
[^]在字符类内使用 ^,表示匹配除括号内字符之外的任何字符。
()定义一个子表达式,可以用于捕获或分组匹配。
\转义字符,用于取消元字符的特殊含义。
{}用于指定重复次数的范围。

group 方法返回匹配的字符串,start 和 end 方法提供起始和结束字符串索引。除此之外,它还有很多其他的方法。

为什么应该使用正则表达式

  1. 数据挖掘:正则表达式是数据挖掘的最佳工具。它通过检查预定义的模式来有效地识别文本堆中的文本。一些常见的场景是从一堆文本中识别电子邮件、URL 或电话。
  2. 数据验证:正则表达式可以完美验证数据。它可以通过定义不同的模式集来包含各种验证过程。一些例子是验证电话号码、电子邮件等。

基本的正则表达式

让我们了解一些基本的正则表达式。它们如下:

  • 字符类
  • 范围
  • 否定/取反
  • 字符串的开头和结尾
  • 任意字符

字符类

字符类允许您将单个字符集与可能的字符集进行匹配。您可以在方括号内提及字符类。下面是一个区分大小写的单词的示例。 

import re


print(re.findall(r'[Gg]eeks', 'GeeksforGeeks: \
				A computer science portal for geeks'))

输出:

['Geeks', 'geeks']

范围

借助范围模式(例如数字范围(0 到 9)、字符范围(A 到 Z)等)提供了匹配文本的灵活性。字符类中的连字符(-)表示一个范围。

import re


print('Range',re.search(r'[a-zA-Z]', 'x'))

输出:

Range <re.Match object; span=(0, 1), match='x'>

否定^

否定会反转字符类。它将查找除字符类中提到的倒置字符或倒置字符范围之外的匹配项。在下面的例子中,r'[^a-z]’ 表示匹配任何不在小写字母范围(a 到 z)内的字符。

import re

print(re.search(r'[^a-z]', 'c'))

输出:

None
import re

print(re.search(r'G[^e]', 'Geeks'))

输出:

None

特殊序列列表

特殊序列描述例子
\A如果字符串以给定字符开头则匹配\Afor for the world
for geeks
\b如果单词以给定字符开头或结尾,则匹配。\b(string) 将检查单词的开头,而 (string)\b 将检查单词的结尾。\bgegeeks
get
\B它与 \b 相反,即字符串不应以给定的正则表达式开头或结尾。\Bgetogether
forge
\d匹配任意十进制数字,相当于集合类[0-9]\d123
gee1
\D匹配任意非数字字符,相当于集合类[^0-9]\Dgeeks
geek1
\s匹配任何空白字符。\sgee ks
a bc a
\S匹配任何非空白字符\Sa bd
abcd
\w匹配任何字母数字字符,这相当于类 [a-zA-Z0-9_]。\w123
geeKs4
\W匹配任何非字母数字字符。\W>$
gee<>
\Z如果字符串以给定的正则表达式结尾则匹配ab\Zabcdab
abababab

让我们讨论一下正则表达式引擎提供的一些快捷方式。

  • \w – 匹配单词字符
  • \d – 匹配数字字符
  • \s – 匹配空白字符(空格、制表符、换行符等)
  • \b – 匹配零长度字符
import re

print('Geeks:', re.search(r'\bGeeks\b', 'Geeks'))               
print('JkhxwforGeeks:', re.search(r'\bGeeks\b', 'JkhxwforGeeks'))

输出:

Geeks: <_sre.SRE_Match object; span=(0, 5), match='Geeks'>
JkhxwforGeeks: None

字符串的开头和结尾

^ 字符选择字符串的开头,$ 字符选择字符串的结尾。

import re


# Beginning of String
match = re.search(r'^Geek', 'Campus Geek of the month')
print('Beg. of String:', match)

match = re.search(r'^Geek', 'Geek of the month')
print('Beg. of String:', match)

# End of String
match = re.search(r'Geeks$', 'JkhxwforGeeks')
print('End of String:', match)

输出:

Beg. of String: None
Beg. of String: <_sre.SRE_Match object; span=(0, 4), match='Geek'>
End of String: <_sre.SRE_Match object; span=(8, 13), match='Geeks'>

任意字符

.字符表示{}字符类之外的任何单个字符。

import re

print('Any Character', re.search(r'p.th.n', 'python 3'))

输出:

Any Character <_sre.SRE_Match object; span=(0, 6), match='python'>

更多正则表达式

可选字符?

正则表达式引擎允许您使用 ? 指定可选字符。它允许字符或字符类出现一次或不出现。

import re


print('Color',re.search(r'colou?r', 'color'))
print('Colour',re.search(r'colou?r', 'colour'))

输出:

Color <_sre.SRE_Match object; span=(0, 5), match='color'>
Colour <_sre.SRE_Match object; span=(0, 6), match='colour'>

重复

重复使您能够重复相同的字符或字符类。考虑一个由日、月和年组成的日期示例。让我们使用正则表达式来标识日期 (mm-dd-yyyy)。

import re


print('Date{mm-dd-yyyy}:', re.search(r'[\d]{2}-[\d]{2}-[\d]{4}','18-08-2020'))

输出:

Date{mm-dd-yyyy}: <_sre.SRE_Match object; span=(0, 10), match='18-08-2020'>

在这里,正则表达式引擎检查两个连续的数字。找到匹配项后,它会移动到连字符。然后,它检查接下来的两个连续数字,并重复该过程。  

重复范围{}

import re


print('Three Digit:', re.search(r'[\d]{3,4}', '189'))
print('Four Digit:', re.search(r'[\d]{3,4}', '2145'))

输出:

Three Digit: <_sre.SRE_Match object; span=(0, 3), match='189'>
Four Digit: <_sre.SRE_Match object; span=(0, 4), match='2145'>

在某些情况下,字符重复没有限制。在这种情况下,您可以将上限设置为不定式。一个常见的例子是匹配街道地址。我们来看一下。

import re

print(re.search(r'[\d]{1,}','5th Floor, A-118,\
Sector-136, Suzhou, Jiangsu - 215000'))

输出:

<_sre.SRE_Match object; span=(0, 1), match='5'>

分组()

分组是使用括号将表达式分成组的过程,它允许您获取每个单独的匹配组。  

import re


grp = re.search(r'([\d]{2})-([\d]{2})-([\d]{4})', '26-08-2020')
print(grp)

输出:

<_sre.SRE_Match object; span=(0, 10), match='26-08-2020'>

返回整个匹配

re 模块允许您使用group()方法返回整个匹配:

import re


grp = re.search(r'([\d]{2})-([\d]{2})-([\d]{4})','26-08-2020')
print(grp.group())

输出:

26-08-2020

您还可以使用 groups() 方法返回包含各个匹配组的元组:

import re


grp = re.search(r'([\d]{2})-([\d]{2})-([\d]{4})','26-08-2020')
print(grp.groups())

输出:

('26', '08', '2020')

继续。将索引传递给组方法后,您可以仅检索单个组。

import re


grp = re.search(r'([\d]{2})-([\d]{2})-([\d]{4})','26-08-2020')
print(grp.group(3))

输出:

2020

re 模块允许您命名您的组。让我们看一下语法。

import re


match = re.search(r'(?P<dd>[\d]{2})-(?P<mm>[\d]{2})-(?P<yyyy>[\d]{4})',
				'26-08-2020')
print(match.group('mm'))

输出:

08

匹配字典

我们已经看到正则表达式如何提供单个组的元组。不仅是元组,它还可以提供单独的匹配作为字典,其中每个组的名称充当字典键。

import re


match = re.search(r'(?P<dd>[\d]{2})-(?P<mm>[\d]{2})-(?P<yyyy>[\d]{4})',
				'26-08-2020')
print(match.groupdict())

输出:

{'dd': '26', 'mm': '08', 'yyyy': '2020'}

替换

正则表达式可以替换字符串,并使用 re.sub 方法返回替换后的字符串。当您希望在将其存储到数据库之前避免使用 /、-、. 等字符时,它非常有用。它需要三个参数:

  • 正则表达式
  • 替换字符串
  • 正在搜索的源字符串

让我们看一下下面的代码,它替换了信用卡号中的– 字符。

import re

print(re.sub(r'([\d]{4})-([\d]{4})-([\d]{4})-([\d]{4})',r'\1\2\3\4',
			'1111-2222-3333-4444'))

输出:

1111222233334444

编译后的正则表达式

Python正则表达式引擎可以使用compile函数返回编译后的正则表达式(RegEx)对象。该对象有其搜索方法和子方法,开发人员可以在需要时重用它。 

import re

regex = re.compile(r'([\d]{2})-([\d]{2})-([\d]{4})')

# search method
print('compiled reg expr', regex.search('26-08-2020'))

# sub method
print(regex.sub(r'\1.\2.\3', '26-08-2020'))

输出:

compiled reg expr <_sre.SRE_Match object; span=(0, 10), match=’26-08-2020′> 26.08.2020

概括

RegEx 是用于数据挖掘和数据验证的强大工具。但是,只要有简单的解决方案,就避免使用正则表达式。而且,当您必须处理复杂的结构(例如重要的文档格式)时,请尝试使用其他满足需求的库。