跳到主要内容

Python 正则表达式

提示

1.正则表达式的定义和用途:正则表达式(RegEx)是一系列字符,用于定义搜索模式,主要用于字符串匹配。例如,^a...s$模式匹配以 "a" 开头以 "s" 结尾的任何五个字母的字符串。

2.Python中的RegEx应用:在Python中,re模块提供了处理RegEx的功能。例如,使用re.match()函数可以在字符串中搜索模式,如果搜索成功,返回一个匹配对象;如果不成功,返回None

3.RegEx元字符和特殊序列:RegEx中的元字符(如[], ^, $, *, +, ?, {}, (), \, |)有特殊的含义,用于创建复杂的搜索模式。特殊序列(如\d, \D, \s, \S, \w, \W)用于匹配数字、字母、空白等特定类型的字符。

正则表达式 Regular Expression(RegEx)是定义搜索模式的一系列字符。例如,

^a...s$

上述代码定义了一个正则表达式模式。该模式是:以a开头,以s结尾的任何五个字母的字符串

使用RegEx定义的模式可以用来匹配字符串。

表达式字符串匹配?
^a...s$abs无匹配
^a...s$alias匹配
^a...s$abyss匹配
^a...s$Alias无匹配
^a...s$An abacus无匹配

Python有一个名为re的模块来处理RegEx。以下是一个例子:

import re

pattern = '^a...s$'
test_string = 'abyss'
result = re.match(pattern, test_string)

if result:
print("搜索成功。")
else:
print("搜索失败。")

这里,我们使用re.match()函数在test_string中搜索模式。如果搜索成功,该方法返回一个匹配对象。如果不成功,则返回None

在re模块中定义了其他几个函数来处理RegEx。在我们探索这些内容之前,让我们先了解一下正则表达式本身。

如果您已经了解RegEx的基础知识,请跳转到Python RegEx

使用RegEx指定模式

要指定正则表达式,使用元字符。在上面的例子中,^$是元字符。

元字符

元字符是由RegEx引擎以特殊方式解释的字符。以下是元字符的列表:

[] . ^ $ * + ? () \ |

[] - 方括号

方括号指定您希望匹配的一组字符。

表达式字符串匹配?
[abc]a1次匹配
[abc]ac2次匹配
[abc]Hey Jude无匹配
[abc]abc de ca5次匹配

这里,[abc]将匹配如果您试图匹配的字符串包含任何abc

您也可以在方括号内使用-指定字符范围。

  • [a-e][abcde]相同。
  • [1-4][1234]相同。
  • [0-39][01239]相同。

您可以通过在方括号开头使用插入符号^来补充(反转)字符集。

  • [^abc]表示除a,b或c以外的任何字符。
  • [^0-9]表示任何非数字字符。

. - 英文句点

句点匹配任何单个字符(除了换行符'\n')。

表达式字符串匹配?
..a无匹配
..ac1次匹配
..acd1次匹配
..acde2次匹配(包含4个字符)

^ - 插入符号

插入符号^用于检查字符串是否以某个特定字符开头。

表达式字符串匹配?
^aa1次匹配
^aabc1次匹配
^abac无匹配
^ababc1次匹配
^abacb无匹配(以a开头但不是跟着b

$ - 美元符号

美元符号

$用于检查字符串是否以某个特定字符结束。

表达式字符串匹配?
a$a1次匹配
a$formula1次匹配
a$cab无匹配

* - 星号

星号*匹配左边模式的零次或多次出现

表达式字符串匹配?
ma*nmn1次匹配
ma*nman1次匹配
ma*nmaaan1次匹配
ma*nmain无匹配(a后面没有跟n
ma*nwoman1次匹配

+ - 加号

加号+匹配左边模式的一次或多次出现

表达式字符串匹配?
ma+nmn无匹配(没有a字符)
ma+nman1次匹配
ma+nmaaan1次匹配
ma+nmain无匹配(a后面没有跟n
ma+nwoman1次匹配

? - 问号

问号?匹配左边模式的零次或一次出现

表达式字符串匹配?
ma?nmn1次匹配
ma?nman1次匹配
ma?nmaaan无匹配(多于一个a字符)
ma?nmain无匹配(a后面没有跟n
ma?nwoman1次匹配

{} - 大括号

考虑这段代码:{n,m}。这意味着左侧模式至少重复n次,最多重复m次。

表达式字符串匹配?
a{2,3}abc dat无匹配
a{2,3}abc daat1次匹配(在daat处)
a{2,3}aabc daaat2次匹配(在aabcdaaat处)
a{2,3}aabc daaaat2次匹配(在aabcdaaaat处)

让我们再尝试一个例子。这个RegEx [0-9]{2, 4}匹配至少2个数字但不超过4个数字

表达式字符串匹配?
[0-9]{2,4}ab123csde1次匹配(在ab123csde处)
[0-9]{2,4}12 and 3456733次匹配(12345673
[0-9]{2,4}1 and 2无匹配

| - 竖线

竖线|用于交替(运算符)。

| 表达式 | 字符串 | 匹配? | | ------ | ------ | -------- | ----------------------- | | a | b | cde | 无匹配 | | a | b | ade | 1次匹配(在ade处) | | a | b | acdbea | 3次匹配(在acdbea处) |

这里,a|b匹配任何包含a或b的字符串

() - 圆括号

圆括号()用于对子模式进行分组。例如,(a|b|c)xz匹配任何匹配a,b或c后面跟着xz的字符串。

| 表达式 | 字符串 | 匹配? | | ------ | ------ | ------ | ----------- | ---------------------------- | | (a | b | c)xz | ab xz | 无匹配 | | (a | b | c)xz | abxz | 1次匹配(在abxz处) | | (a | b | c)xz | axz cabxz | 2次匹配(在axzbc cabxz处) |

\ - 反斜杠

反斜杠\用于转义包括所有元字符在内的各种字符。例如,

\$a匹配如果字符串包含$后跟a。这里,$不会以特殊方式被RegEx引擎解释。

如果您不确定字符是否有特殊含义,可以在其前面加上\。这确保字符不会以特殊方式处理。

特殊序列

特殊序列使常用模式更容易编写。以下是特殊序列的列表:

\A - 如果指定的字符在字符串的开头匹配。

表达式字符串匹配?
\Athethe sun匹配
\AtheIn the sun无匹配

\b - 如果指定的字符在单词的开头或结尾匹配。

| 表达式 | 字符串 | 匹配? | | ------- | --------------- | --------- | ---- | | \bfoo | football | 匹配 | | \bfoo | a football | 匹配 | | \bfoo | afootball | 无匹配 | | \bfoo | foo\b | the foo | 匹配 | | \bfoo | the afoo test | 匹配 | | \bfoo | the afootest | 无匹配 |

\B - \b的相反。如果指定的字符在单词的开头或结尾匹配。

| 表达式 | 字符串 | 匹配? | | ------- | --------------- | --------- | ------ | | \Bfoo | football | 无匹配 | | \Bfoo | a football | 无匹配 | | \Bfoo | afootball | 匹配 | | \Bfoo | foo\B | the foo | 无匹配 | | \Bfoo | the afoo test | 无匹配 | | \Bfoo | the afootest | 匹配 |

\d - 匹配任何十进制数字。等同于[0-9]

表达式字符串匹配?
\d12abc33次匹配(在12abc3处)
\dPython无匹配

\D - 匹配任何非十进制数字。等同于[^0-9]

表达式字符串匹配?
\D1ab34"503次匹配(在1ab34"50处)
\D1345无匹配

\s - 匹配字符串中包含任何空白字符的地方。等同于[ \t\n\r\f\v]

表达式字符串匹配?
\sPython RegEx1次匹配
\sPythonRegEx无匹配

\S - 匹配字符串中包含任何非空白字符的地方。等同于[^ \t\n\r\f\v]

Markdown格式文本:

表达式字符串匹配情况
\Sa b2次匹配(在 a b处)
\S   无匹配

\w - 匹配任何字母数字字符(数字和字母)。等同于[a-zA-Z0-9_]。顺便说一下,下划线_也被视为字母数字字符。

表达式字符串匹配情况
\w12&": ;c 3次匹配(在12&": ;c处)
\w%"> !无匹配

\W - 匹配任何非字母数字字符。等同于[^a-zA-Z0-9_]

表达式字符串匹配情况
\W1a2%c1次匹配(在1a2%c处)
\WPython无匹配

\Z - 如果指定的字符在字符串的末尾,则匹配。

表达式字符串匹配情况
Python\ZI like Python1次匹配
Python\ZI like Python Programming无匹配
Python\ZPython is fun.无匹配

小贴士: 要构建和测试正则表达式,您可以使用诸如regex101的RegEx测试工具。这个工具不仅帮助您创建正则表达式,而且还帮助您学习它。

现在您了解了RegEx的基础知识,让我们讨论如何在Python代码中使用RegEx。

Python正则表达式

Python有一个名为re的模块用于处理正则表达式。要使用它,我们需要导入该模块。

import re

该模块定义了几个函数和常量用于处理RegEx。

re.findall()

re.findall()方法返回一个字符串列表,包含所有匹配项。

示例 1: re.findall()


# 程序用于从字符串中提取数字
import re

string = 'hello 12 hi 89. Howdy 34'
pattern = '\d+'

result = re.findall(pattern, string)
print(result)

# 输出: ['12', '89', '34']

如果模式未找到,re.findall()返回一个空列表。

re.split()

re.split方法在匹配处分割字符串,并返回分割发生处的字符串列表。

示例 2: re.split()


import re

string = 'Twelve:12 Eighty nine:89.'
pattern = '\d+'

result = re.split(pattern, string)
print(result)

# 输出: ['Twelve:', ' Eighty nine:', '.']

如果模式未找到,re.split()返回包含原始字符串的列表。

您可以向re.split()方法传递maxsplit参数。这是将发生的最大分割次数。


import re

string = 'Twelve:12 Eighty nine:89 Nine:9.'
pattern = '\d+'

# maxsplit = 1
# 仅在第一次出现时分割
result = re.split(pattern, string, 1)
print(result)

# 输出: ['Twelve:', ' Eighty nine:89 Nine:9.']

顺便说一下,maxsplit的默认值是0;意味着所有可能的分割。

re.sub()

re.sub()的语法是:

re.sub(pattern, replace, string)

该方法返回一个字符串,其中匹配的出现被替换变量replace的内容所替换。

示例 3: re.sub()


# 程
序用于删除所有空白字符

import re

# 多行字符串
string = 'abc 12\
de 23 \n f45 6'

# 匹配所有空白字符
pattern = '\s+'

# 空字符串
replace = ''

new_string = re.sub(pattern, replace, string)
print(new_string)

# 输出: abc12de23f456

如果模式未找到,re.sub()返回原始字符串。

您可以向re.sub()方法传递count作为第四个参数。如果省略,其结果为0。这将替换所有出现。


import re

# 多行字符串
string = 'abc 12\
de 23 \n f45 6'

# 匹配所有空白字符
pattern = '\s+'
replace = ''

new_string = re.sub(r'\s+', replace, string, 1)
print(new_string)

# 输出:
# abc12de 23
# f45 6

re.subn()

re.subn()re.sub()类似,不同之处在于它返回一个包含新字符串和所做替换次数的2项元组。

示例 4: re.subn()


# 程序用于删除所有空白字符
import re

# 多行字符串
string = 'abc 12\
de 23 \n f45 6'

# 匹配所有空白字符
pattern = '\s+'

# 空字符串
replace = ''

new_string = re.subn(pattern, replace, string)
print(new_string)

# 输出: ('abc12de23f456', 4)

re.search()

re.search()方法接受两个参数:一个模式和一个字符串。该方法查找RegEx模式与字符串首次匹配的位置。

如果搜索成功,re.search()返回一个匹配对象;如果不成功,则返回None

match = re.search(pattern, str)

示例 5:re.search()


import re

string = "Python很有趣"

# 检查'Python'是否在开头
match = re.search('\APython', string)

if match:
print("在字符串中找到了模式")
else:
print("未找到模式")

# 输出:在字符串中找到了模式

这里,match包含一个匹配对象。

匹配对象

您可以使用dir()函数获取匹配对象的方法和属性。

匹配对象常用的一些方法和属性包括:

match.group()

group()方法返回匹配的字符串部分。

示例 6:匹配对象


import re

string = '39801 356, 2102 1111'

# 三位数字后面跟着空格再跟着两位数字
pattern = '(\d{3}) (\d{2})'

# match变量包含一个匹配对象。
match = re.search(pattern, string)

if match:
print(match.group())
else:
print("未找到模式")

# 输出:801 35

这里,match变量包含一个匹配对象。

我们的模式(\d{3}) (\d{2})有两个子组(\d{3})(\d{2})。您可以获取这些带括号子组的字符串部分。方法如下:

>>> match.group(1)
'801'

>>> match.group(2)
'35'
>>> match.group(1, 2)
('801', '35')

>>> match.groups()
('801', '35')

match.start()、match.end()和match.span()

start()函数返回匹配子串的开始索引。同样,end()返回匹配子串的结束索引。

>>> match.start()
2
>>> match.end()
8

span()函数返回一个元组,包含匹配部分的开始和结束索引。

>>> match.span()
(2, 8)

match.re和match.string

匹配对象的re属性返回一个正则表达式对象。同样,string属性返回传递的字符串。

>>> match.re
re.compile('(\\d{3}) (\\d{2})')

>>> match.string
'39801 356, 2102 1111'

我们已经介绍了re模块中所有常用的方法。如果您想了解更多,请访问Python 3 re模块

在RegEx之前使用r前缀

在正则表达式之前使用r或R前缀意味着原始字符串。例如,'\n'是一个新行,而r'\n'表示两个字符:一个反斜杠\后面跟着一个n

反斜杠\用于转义各种字符,包括所有元字符。然而,使用r前缀使\被当作普通字符处理。

示例 7:使用r前缀的原始字符串


import re

string = '\n 和 \r 是转义序列。'

result = re.findall(r'[\n\r]', string)
print(result)

# 输出:['\n', '\r']