正则表达式是一种用单一模式表达与指定条件匹配的多个字符串的方法。Python 和许多其他编程语言都可以使用正则表达式,但是每种语言都有不同的描述方式,并且可能会给出不同的结果。在本文中,我将解释如何在 Python 中使用正则表达式。
目录
16-1 如何在 Python 中使用正则表达式
16-2 从模式 (Pattern) 创建正则表达式对象
16-3 查找字符串中的任何位置是否与模式匹配 (Pattern.search)
16-4 检查模式是否从字符串的开头匹配(Pattern.match)
16-5 检查整个字符串是否匹配模式(Pattern.fullmatch)
16-6 获取与模式匹配的所有字符串的列表(Pattern.findall)
16-7 获取匹配某个模式的所有匹配对象(Pattern.finditer)
16-8 从匹配对象(Match)中获取匹配字符串的信息
16-9 使用正则表达式模式作为分隔符拆分字符串(Pattern.split)
16-10 将与正则表达式匹配的字符串替换为新字符串(Pattern.sub, Pattern.subn)
正则表达式可用于各种编程语言,这一张我们将简要说明如何在 Python 中使用正则表达式。更详细的使用方法请参考以下页面。
定义一个模式
正则表达式用于在文本中搜索条件稍微复杂的目标字符串,或者检查用户输入的值是否与指定的字符类型或格式匹配。该功能方便 例如,不是检查目标文本是否包含字符串“ABCD”,而是检查它是否包含以“A”开头并以“D”结尾的四个字母的字符串。
模式定义了在这句话中寻找什么样的字符串。
模式是使用字符串或特殊的预先确定的符号定义的。例如,表示以“a”开头并以“e”结尾的 5 个字符的字符串的模式可以定义为“a…e”。正则表达式中的点 (.) 表示任何单个字符。
定义模式后,创建 Pattern 类的实例以使用该模式来匹配目标字符串。要创建它,请使用 re 模块中的compile函数并编写:
import re
pattern = re.compile(r'a...e')
compile函数的参数是表示模式的字符串。它可能是一个正则字符串,但正则表达式经常使用反斜杠(Windows 上的反斜杠),所以我更喜欢原始字符串,其中反斜杠可以被视为字符而不是特殊字符。结果,您可以获得 Pattern 类的一个实例。
检查一个句子是否匹配一个模式
然后检查目标字符串是否与模式匹配。匹配意味着目标字符串包含与模式匹配的字符串。
有几种方法可以找出目标字符串是否与模式匹配,但这里我们将使用 Pattern 类提供的搜索方法。
target = 'apple and orange'
pattern = re.compile(r'a...e')
result = pattern.search(target)
如果目标字符串与模式匹配,则返回 Match 类的对象,如果不匹配,则返回 None 。
现在,让我们得到目标句子的哪一部分匹配。
import re
target = 'apple and orange'
pattern = re.compile(r'a.{3}e')
result = pattern.search(target)
if result :
print(result.group())
>> apple
在本例中,模式匹配目标字符串的“apple”部分。
要使用正则表达式,您需要确切地知道如何编写模式,以及该模式实际匹配的文本。我们将从下一页开始按顺序进行说明。
模式定义使用正则表达式匹配的字符串类型。在这里,在将模式定义为字符串之后,我们将解释如何从模式中获取正则表达式对象(Pattern 类的实例)。
定义一个模式
首先将模式定义为字符串。例如,模式是 ‘abc’ 以检查目标文本是否包含字符串 abc。
pat = 'abc'
正则表达式还允许您使用具有特殊含义的字符(称为元字符)来定义模式。例如,检查目标字符串结尾是否以 png 结尾的模式是 ‘png$’。’$’ 是一个匹配字符串结尾的元字符。
pat = 'png$'
定义模式时使用的一些元字符时使用反斜杠“\”。例如,’\w’ 代表字母数字字符和下划线。如果将模式写为字符串,则反斜杠在字符串中具有特殊含义,必须按如下方式进行转义:
pat = '\\w'
在那里定义模式时,使用原始字符串而不是常规字符串很有用。反斜杠可以写成未转义的原始字符串,所以上面的模式可以写成:
pat = r'\w'
编译模式
在Python中使用正则表达式时,一种方法是使用定义为模式的字符串,使用re模块中包含的函数,编译模式并创建Pattern类的实例后,Pattern类的方法有一个使用方法
如果只使用该模式一次,则不必编译它,但如果重复使用相同的模式,则最好编译它。以后我会讲解编译后的使用方法。
要compile模式并创建 Pattern 类的实例,请使用 re 模块中的编译函数。
re.compile(pat, flags=0)
第一个参数是表示模式的字符串。第二个可选参数指定flag。flag在另一页上解释。
具体写如下。
import re
pattern = re.compile(r'png$')
一旦有了 Pattern 类的实例,就可以使用 Pattern 提供的方法来检查目标句子是否与模式匹配。
示例代码
请看下面的示例。
import re
filename = 'apple.png'
pattern = re.compile(r'png$')
result = pattern.search(filename)
if result :
print('匹配模式')
else :
print('不匹配模式)
>> 匹配模式
检查目标字符串是否与模式匹配并显示它。
Pattern 类的搜索方法测试目标字符串的模式匹配,从字符串的开头开始,在字符串的任何位置寻找匹配项。在这里,我将解释如何使用带有 Python 正则表达式的搜索方法来检查模式是否在字符串中的任何位置匹配。
search方法的格式和用法
Pattern 类的search方法从目标字符串的开头搜索模式匹配。格式如下。
Pattern.search(string[, pos[, endpos]])
将目标字符串指定为第一个参数。它从字符串的开头开始依次检查模式是否匹配,如果匹配则返回一个匹配对象(Match类的一个实例)。如果字符串末尾没有匹配项,则返回 None。
可选的第二个和第三个参数指定检查目标字符串中匹配项的范围。范围是从 pos 到 endpos – 1。pos的初值为0,endpos的初值为字符串的长度。
如果search方法找到一个成功的匹配,你将得到一个匹配对象作为返回值。如果将得到的匹配对象写在条件表达式中,则始终判断为True。反之,匹配失败返回的None写入条件表达式时判断为False。
因此,可以通过下面的if语句来判断是否执行了search方法,是否匹配成功。
import re
msg = 'lemon, apple, peach'
pattern = re.compile(r'apple')
result = pattern.search(msg)
if result :
print('Matched')
else :
print('Don\'t matched')
>> Matched
得到匹配的字符串
获取匹配对象作为search方法的返回值后,可以使用Match类提供的方法获取字符串中与模式匹配的部分,或者获取字符串中与模式匹配的索引。我可以.
这一次,我们将使用 Match 类的 group 方法来获取与模式匹配的整个字符串。请看下面的示例。
import re
def checkMatch(msg, pattern):
result = pattern.search(msg)
if result :
print(result.group(0))
else :
print('Don\'t matched')
pattern = re.compile(r'apple')
checkMatch('lemon, apple, peach', pattern)
>> apple
checkMatch('grapes, cherry', pattern)
>> Don\'t matched/span>
我们检查了目标字符串是否与模式匹配,如果匹配,我就得到了匹配的字符串。
设置检查范围
通过指定搜索方法的第二个和第三个参数,您可以设置要检查目标字符串的范围。例如,如果目标字符串是“山东省青岛市市南区”,并且在搜索方法中省略了第二个和第三个参数,则“山东省青岛市市南区”将成为目标。
如果将 3 指定为匹配方法的第二个参数并将 6 指定为第三个参数,则目标字符串将为“东省青”。
请看下面的示例。字符串是一样的,只是目标范围变了,执行了match方法。
import re
def checkMatch(msg, pattern, start, end):
result = pattern.search(msg, start, end)
if result :
print(result.group(0))
else :
print('Don\'t matched')
msg = '山东省青岛市市南区'
pattern = re.compile(r'山东')
checkMatch(msg, pattern, 0, 7)
>> 山东
checkMatch(msg, pattern, 1, 4)
>> Don\'t matched
match 方法只从字符串的开头检查是否匹配,但是如果你设置了目标字符串的范围,它会进行第二次匹配,检查是否从设置范围的第一个字符开始匹配。
Pattern 类的 match 方法检查模式是否匹配目标字符串的开头。search 方法检查字符串中的任何位置是否匹配,而 match 方法仅检查字符串开头的匹配项。在这里,我将解释如何使用带有 Python 正则表达式的 match 方法来检查模式是否从字符串的开头开始匹配。
match匹配方法的格式和用法
Pattern 类的 match 方法检查模式是否匹配目标字符串的开头。格式如下。
Pattern.match(string[, pos[, endpos]])
将目标字符串指定为第一个参数。检查模式是否与字符串的开头匹配,如果匹配则返回匹配对象(Match 类的实例)。如果没有匹配项,则返回 None。
可选的第二个和第三个参数指定检查目标字符串中匹配项的范围。范围是从 pos 到 endpos – 1。
match 方法类似于 search 方法,不同之处在于 search 方法搜索整个字符串以查看它是否与模式匹配,而 match 方法检查它是否仅从字符串的开头匹配。
因此,如果目标字符串是”山东省青岛市市南’并且模式是’青岛市’,则搜索方法会匹配,但匹配方法不会匹配。如果模式是“山东”,这两种方法都会匹配。
请看下面的示例。使用 match 方法检查匹配项,如果匹配,则检索匹配的子字符串。
import re
def checkMatch(msg, pat):
pattern = re.compile(pat)
result = pattern.match(msg)
if result :
print(result.group(0))
else :
print('Don\'t matched')
checkMatch('山东省青岛市市南区', r'山东.')
>> 山东省
checkMatch('山东省青岛市市南区', r'青.')
>> Don't matched
我们学习了目标字符串是否与模式匹配,如果匹配,我就得到了匹配的字符串。
设置检查范围
通过指定 match 方法的第二个和第三个参数,您可以设置检查目标字符串的范围。例如,如果目标字符串是’山东省青岛市市南’,如果在匹配方法中省略第二个和第三个参数,’山东省青岛市市南’将成为目标。
如果将 3 指定为匹配方法的第二个参数并将 5 指定为第三个参数,则目标字符串将为“青岛”。
次のサンプルを見てください。文字列は同じですが、対象の範囲を変えて match メソッドを実行しています。
import re
def checkMatch(msg, pattern, start, end):
result = pattern.match(msg, start, end)
if result :
print(result.group(0))
else :
print('Don\'t matched')
msg = '山东省青岛市市南'
pattern = re.compile(r'青岛')
checkMatch(msg, pattern, 0, 7)
>> Don't matched
checkMatch(msg, pattern, 3, 7)
>> 青岛
match 方法只从字符串的开头检查是否匹配,但是如果你设置了目标字符串的范围,它会进行第二次匹配,检查是否从设置范围的第一个字符开始匹配。
Pattern 类的 fullmatch 方法测试整个目标字符串是否与模式匹配。即使目标字符串的一部分匹配,fullmatch 方法也不会匹配。在这里,我将解释如何使用 Python 的正则表达式中的 fullmatch 方法来检查整个字符串是否与模式匹配。
全匹配方法的格式和用法(Pattern.fullmatch)
Pattern 类的 fullmatch 方法测试整个目标字符串是否与模式匹配。格式如下。
Pattern.fullmatch(string[, pos[, endpos]])
将目标字符串指定为第一个参数。检查模式是否匹配整个字符串,如果匹配则返回一个匹配对象(Match 类的一个实例)。如果没有匹配项,则返回 None。
可选的第二个和第三个参数指定检查目标字符串中匹配项的范围。范围是从 pos 到 endpos – 1。
fullmatch 方法类似于search 方法,不同之处在于search 方法搜索整个字符串以查看是否有任何部分与模式匹配,而fullmatch 方法将整个字符串匹配到模式。
因此,如果目标字符串是’Akasaka, Minato-ku, Tokyo’并且模式是’Minato-ku’,则搜索方法会匹配,但匹配方法不会匹配。如果模式是“Akasaka, Minato-ku, Tokyo”,这两种方法都会匹配。
请看下面的示例。使用 fullmatch 方法检查是否匹配,如果是,则检索匹配的子字符串。
import re
def checkMatch(msg, pat):
pattern = re.compile(pat)
result = pattern.fullmatch(msg)
if result :
print(result.group(0))
else :
print('Don\'t matched')
checkMatch('山东省青岛市市南区', r'山.*市')
>> Don't matched
checkMatch('山东省青岛市市南区', r'山.*区')
>> 山东省青岛市市南区
我们学习了目标字符串是否与模式匹配,如果匹配,我就得到了匹配的字符串。
设置检查范围
通过指定 fullmatch 方法的第二个和第三个参数,您可以设置检查目标字符串的范围。例如,如果目标字符串是’山东省青岛市市南区’,如果在 fullmatch 方法中省略第二个和第三个参数,’山东省青岛市市南区’ 将成为目标。
如果将 3 指定为 fullmatch 方法的第二个参数并将 5 指定为第三个参数,则目标字符串将为“青岛市”。
请看下面的示例。字符串相同,但目标范围发生了变化,并运行了全匹配方法。
import re
def checkMatch(msg, pattern, start, end):
result = pattern.fullmatch(msg, start, end)
if result :
print(result.group(0))
else :
print('Don\'t matched')
msg = '山东省青岛市市南区'
pattern = re.compile(r'青岛市')
checkMatch(msg, pattern, 0, 5)
>> Don't matched
checkMatch(msg, pattern, 3, 5)
>> 青岛市
fullmatch 方法检查整个字符串是否与模式匹配,但是如果你设置了一个目标字符串范围,它会进行第二次匹配以检查整个设置范围的字符串是否与模式匹配。
Pattern 类的 findall 方法检索目标字符串中与模式匹配的所有字符串的列表。在这里,我将解释如何使用 Python 正则表达式中的 findall 方法获取列表中所有匹配的字符串。
findall方法的格式和用法
Pattern 类的 findall 方法检索目标字符串中与模式匹配的所有字符串的列表。格式如下。
Pattern.findall(string[, pos[, endpos]])
将目标字符串指定为第一个参数。它从头开始检查字符串是否匹配,并将所有匹配的字符串作为列表返回。如果没有匹配项,则返回一个空列表。
可选的第二个和第三个参数指定检查目标字符串中匹配项的范围。范围是从 pos 到 endpos – 1。
findall 方法返回一个以匹配字符串作为元素的列表。请看下面的示例。
import re
msg = 'MA-52, JO-72, PP-45'
pattern = re.compile(r'[A-Z]{2}-[0-9]{2}')
result = pattern.findall(msg)
if (len(result) == 0):
print('Don\'t matched')
else:
for s in result:
print(s)
>> MA-52
>> JO-72
>> PP-45
在此示例中,模式匹配目标字符串中的 3 个位置。我使用 for 语句从包含匹配字符串的列表中按顺序挑选出元素。如果没有匹配项,则返回一个空列表,因此如果使用 len 函数的元素数为 0,则将其视为没有匹配项。
如果捕获组设置为 pattern
如果模式具有捕获组,则返回一个元组列表,其元素是与每个捕获组匹配的字符串。请看下面的示例。
import re
msg = 'MA-52, JO-72, PP-45'
pattern = re.compile(r'([A-Z]{2})-([0-9]{2})')
result = pattern.findall(msg)
if (len(result) == 0):
print('Don\'t matched')
else:
for s in result:
print(s)
>> ('MA', '52')
>> ('JO', '72')
>> ('PP', '45')
在本例中,模式中设置了两个捕获组。因此,每匹配一次,就得到一个元组,其元素是匹配每个捕获组的字符串,最后得到一个列表,其元素是元组。
Pattern 类的 finditer 方法为目标字符串中与模式匹配的所有匹配对象获取一个迭代器。在这里,我们将看到如何使用 Python 正则表达式中的 finditer 方法来获取与模式匹配的所有匹配对象。
finditer方法的格式和使用
Pattern 类的 finditer 方法为目标字符串中与模式匹配的所有匹配对象获取一个迭代器。格式如下。
Pattern.finditer(string[, pos[, endpos]])
将目标字符串指定为第一个参数。返回一个迭代器以获取与模式匹配的所有匹配对象,从字符串的开头开始。
可选的第二个和第三个参数指定检查目标字符串中匹配项的范围。范围是从 pos 到 endpos – 1。
finditer 方法返回一个迭代器来检索匹配对象,因此您可以使用迭代器顺序检索与模式匹配的匹配对象。请看下面的示例。
import re
msg = 'MA-52, JO-72, PP-45'
pattern = re.compile(r'[A-Z]{2}-[0-9]{2}')
result = pattern.finditer(msg)
for m in result:
print(m.group())
>> MA-52
>> JO-72
>> PP-45
在此示例中,模式匹配目标字符串中的 3 个位置。一旦你有了匹配部分的匹配对象,你就可以使用 Match 类的方法来获取匹配的字符串,等等。在这个例子中,我们使用了Match类的group方法来获取匹配的字符串。
如果模式设置了捕获组
如果在模式中设置了捕获组,则可以从匹配对象中单独检索与捕获组匹配的字符串。请看下面的示例。
import re
msg = 'MA-52, JO-72, PP-45'
pattern = re.compile(r'([A-Z]{2})-([0-9]{2})')
result = pattern.finditer(msg)
for m in result:
print('Match:' + m.group(0))
print('Group1:' + m.group(1))
print('Group2:' + m.group(2))
>> Match:MA-52
>> Group1:MA
>> Group2:52
>> Match:JO-72
>> Group1:JO
>> Group2:72
>> Match:PP-45
>> Group1:PP
>> Group2:45
在检索到与整个模式匹配的字符串后,我们为每个捕获组检索匹配的子字符串。
如果模式不匹配怎么办
如果使用 finditer 方法,返回值将是一个迭代器。例如,如果要添加不匹配的处理,请执行以下操作。
import re
msg = 'Sample'
pattern = re.compile(r'[A-Z]{2}-[0-9]{2}')
result = pattern.finditer(msg)
m = None
for m in result:
print(m.group())
if m is None:
print('Don\'t matched')
>> Don't matched
为存储使用迭代器检索到的匹配对象的变量提前设置 None。如果没有从迭代器中提取匹配对象,则变量仍然是 None,所以我们使用 if 语句检查变量的值,如果它仍然是 None,则字符串不匹配模式。
当一个字符串用Pattern类的search方法或match方法匹配一个模式时,它返回一个匹配对象作为返回值。匹配对象可以使用 Match 类提供的方法来检索匹配的字符串或匹配部分在目标字符串中的索引。在这里,我将解释如何从Python匹配对象中获取匹配的字符串等信息。
获取匹配字符串(group)
Match 类的 group 方法返回整个匹配字符串或捕获组匹配的子字符串。格式如下。
Match.group([group1, ...])
如果参数为 0 或省略,则返回与模式匹配的整个字符串。大于或等于 1(最多 99)的值返回与相应捕获组匹配的子字符串。
result = Match.group(0)
如果您使用命名捕获组,您还可以将捕获组名称指定为字符串而不是参数中的数字。
如果只指定一个参数,它将作为一个字符串返回,如果指定两个或多个,它将返回一个元组,每个结果作为一个元素。
result = Match.group(1, 2)
获取与模式匹配的整个字符串
首先尝试获取与模式匹配的整个字符串。请看下面的示例。
import re
msg = 'My birthday is 1996/04/06'
pattern = re.compile(r'\d{4}/\d{2}/\d{2}')
result = pattern.search(msg)
if result :
print('Match:' + result.group(0))
>> Match:1996/04/06
我能够得到与模式匹配的整个字符串。
获取匹配捕获组的子串
接下来,在模式中设置捕获组并尝试获取每个捕获组匹配的子字符串。请看下面的示例。
import re
msg = 'My birthday is 1996/04/06'
pattern = re.compile(r'(\d{4})/(\d{2})/(\d{2})')
result = pattern.search(msg)
if result :
print('Match:' + result.group(0))
print('Group1:' + result.group(1))
print('Group2:' + result.group(2))
print('Group3:' + result.group(3))
>> Match:1996/04/06
>> Group1:1996
>> Group2:04
>> Group3:06
我能够获得与模式中设置的捕获组匹配的每个子字符串。
获取与命名捕获组匹配的子字符串
接下来,在模式中设置命名的捕获组,并尝试获取每个捕获组匹配的子字符串。请看下面的示例。
import re
msg = 'My birthday is 1996/04/06'
pattern = re.compile(r'(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})')
result = pattern.search(msg)
if result :
print('Match:' + result.group(0))
print('Group[year]:' + result.group('year'))
print('Group[month]:' + result.group('month'))
print('Group[day]:' + result.group('day'))
>> Match:1996/04/06
>> Group[year]:1996
>> Group[month]:04
>> Group[day]:06
我能够获得与模式中设置的命名捕获组匹配的每个子字符串。
获取多个匹配字符串作为一个元组
接下来,在模式中设置捕获组,并获取每个捕获组匹配的子字符串作为元组。请看下面的示例。
import re
msg = 'My birthday is 1996/04/06'
pattern = re.compile(r'(\d{4})/(\d{2})/(\d{2})')
result = pattern.search(msg)
if result :
print(result.group(1, 2, 3))
>> ('1996', '04', '06')
这样我们就能够获得与模式中设置的捕获组匹配的子字符串元组。
获取匹配字符串的首尾索引(start方法,end方法)
Match 类的 start 方法返回捕获组匹配的整个匹配字符串或子字符串的开头索引。同样,end 方法返回匹配字符串结尾的索引(最后一个字符的旁边)。格式如下。
Match.start([group])
Match.end([group])
如果参数为 0 或省略,则返回与模式匹配的整个字符串的索引。大于或等于 1(最多 99)的值返回与相应捕获组匹配的子字符串的索引。
sindex = Match.start(0)
eindex = Match.end(0)
获取与模式匹配的整个字符串的索引
首先尝试获取与模式匹配的整个字符串的索引。请看下面的示例。
import re
msg = 'My birthday is 1996/04/06'
pattern = re.compile(r'\d{4}/\d{2}/\d{2}')
result = pattern.search(mg)
if result :
print('Match:' + result.group(0))
print('StartIndex:' + str(result.start(0)))
print('EndIndex:' + str(result.end(0)))
>> Match:1996/04/06
>> StartIndex:15
>> EndIndex:25
我能够获得与模式匹配的整个字符串的开始和结束索引。在这种情况下,匹配字符串中第一个字符的索引是 15,结尾(最后一个字符旁边)的索引是 25。
获取捕获组匹配的子串的索引
接下来,在模式中设置捕获组并获取与第一个捕获组匹配的子字符串的索引。请看下面的示例。
import re
msg = 'My birthday is 1996/04/06'
pattern = re.compile(r'(\d{4})/(\d{2})/(\d{2})')
result = pattern.search(msg)
if result :
print('Group1:' + result.group(1))
print('StartIndex:' + str(result.start(1)))
print('EndIndex:' + str(result.end(1)))
>> Group1:1996
>> StartIndex:04
>> EndIndex:06
我能够获得与模式中设置的捕获组中的第一个捕获组匹配的子字符串的索引。在这种情况下,与第一个捕获组匹配的字符串的第一个字符的索引为 15,最后一个字符(最后一个字符的旁边)的索引为 19。
指的是最后匹配的捕获组的索引(lastindex)
Match 类的一个属性 lastindex 包含最后一个匹配捕获组的索引。
Match.lastindex
如果没有组匹配,则 None 不会被存储。
示例代码
请看下面的示例。
import re
msg = 'My birthday is 1996/04/06'
pattern = re.compile(r'(\d{4})/(\d{2})/(\d{2})')
result = pattern.search(msg)
if result :
for i in range(result.lastindex):
print('Group:' + str(i + 1) + ' ' + result.group(i + 1))
>> Group:1 1996
>> Group:2 04
>> Group:3 06
这样我们就能够获得与模式中设置的捕获组匹配的子字符串的索引。在这种情况下,最后匹配的捕获组的索引是 3。
Pattern类的split方法以正则表达式模式为分隔符对目标字符串进行拆分,得到一个列表,其元素为拆分后的字符串。在这里,我将解释如何使用 Python 正则表达式中的 split 方法以正则表达式模式拆分字符串。
split方法的格式和用法
Pattern类的split方法将目标字符串按照指定的正则表达式模式进行拆分,得到一个列表,其元素为拆分后的字符串。格式如下。
Pattern.split(string, maxsplit=0)
将目标字符串指定为第一个参数。可选的第二个参数指定最大拆分数。默认值为 0,即允许拆分次数不受限制。
请看下面的示例。
import re
msg = '你好。今天的早点是,面包,牛奶,鸡蛋。'
pattern = re.compile(r'。|,')
result = pattern.split(msg)
print(result)
>> ['你好', '今天的早点是', '面包', '牛奶', '鸡蛋', '']
for s in result:
print(s)
>> 你好
>> 今天的早点是
>> 面包
>> 牛奶
>> 鸡蛋
>>
我们指定了匹配“。”或“,”的模式作为正则表达式模式。我能够使用与模式匹配的定界符拆分目标字符串,并获得一个以拆分字符串作为元素的列表。
请注意,如果模式在开头或结尾匹配,则空字符串元素如果是开头则包含在列表的开头,如果是结尾则包含在列表的结尾。
指定分割数
我们可以在 split 方法的第二个参数中指定最大拆分数。例如,如果指定2,则目标字符串将被拆分两次,结果将得到一个以三个子字符串为元素的列表。
请看下面的示例。
import re
msg = '你好。今天的早点是,面包,牛奶,鸡蛋。'
pattern = re.compile(r'。|,')
result = pattern.split(msg, 2)
print(result)
>> ['你好', '今天的早点是', '面包,牛奶,鸡蛋。']
由于指定最大分割数为2,因此将目标字符串分割为3份,得到以每个字符串为元素的列表。将字符串拆分为最大拆分次数指定的次数后,将剩余的字符串收集为最终的子字符串。
Pattern 类的 sub 方法将目标字符串中与正则表达式模式匹配的字符串替换为新字符串。sub 方法返回替换后的新字符串,而 subn 方法将其作为元组返回。本节介绍如何使用Python正则表达式中的sub方法和subn方法将匹配正则表达式的字符串替换为新的字符串。
sub方法的格式和使用
Pattern 类的 sub 方法用新字符串替换目标字符串中与正则表达式模式匹配的子字符串,并返回替换后的字符串。格式如下。
Pattern.sub(repl, string, count=0)
Pattern 类的 subn 方法与 sub 方法的工作原理相同,但不是返回替换后的字符串,而是返回一个包含两个元素的元组:新字符串和替换次数。格式如下。
Pattern.subn(repl, string, count=0)
这两种方法都将要替换的新字符串作为第一个参数,将目标字符串作为第二个参数。可选的第三个参数指定最大替换次数。默认值为 0,允许无限次替换。
首先关于子方法。请看下面的示例。
import re
msg = 'Border is Red, Box is red, Line is RED'
pattern = re.compile(r'Red|RED')
result = pattern.sub('red', msg)
print(result)
>> Border is red, Box is red, Line is red
我们将匹配“Red”或“RED”的模式指定为正则表达式模式,并将与该模式匹配的字符串替换为“red”。作为返回值,我们在替换后得到一个新字符串。
接下来是 subn 方法。请看下面的示例。
import re
msg = 'Border is Red, Box is red, Line is RED'
pattern = re.compile(r'Red|RED')
result = pattern.subn('red', msg)
print(result)
>> ('Border is red, Box is red, Line is red', 2)
我将匹配“Red”或“RED”的模式指定为正则表达式模式,并将与该模式匹配的字符串替换为“red”。作为返回值,我们得到一个元组,其中替换后的新字符串和执行替换的次数作为元素存储。
指定替换次数
我们还可以在 sub(和 subn)方法的第二个参数中指定最大替换次数。例如,如果指定 2,则目标字符串最多被替换 2 次。
请看下面的示例。
import re
msg = 'Red Blue Yellow Pink Green White'
pattern = re.compile(r'\b[a-zA-Z]+?\b')
result = pattern.sub('***', msg)
print(result)
>> *** *** *** *** *** ***
此示例将所有单词替换为 ***。所有单词都已被替换,因为没有限制替换次数。
接下来,让我们在前面的示例中将最大替换次数设置为 2。
import re
msg = 'Red Blue Yellow Pink Green White'
pattern = re.compile(r'\b[a-zA-Z]+?\b')
result = pattern.sub('***', msg, 2)
print(result)
>> *** *** Yellow Pink Green White
这次最多替换2个,所以只替换前两个词,剩下的词不用管。通过这种方式设置最大替换次数,可以限制最大替换次数。
引用捕获组匹配的字符串
在sub方法(和sub2方法)中,如果捕获组包含在正则表达式中,则在字符串中使用\1,\2,…来替换捕获组捕获的内容,可以参考字符串。
\1, \2, ... 捕获组捕获的字符串
请看下面的示例。
import re
msg = '下一次会议是 2020-12-03'
pattern = re.compile(r'(\d{4})-(\d{2})-(\d{2})')
result = pattern.sub(r'\1年\2月\3日', msg)
print(result)
>> 下一次会议是2020年12月03日
在我们的示例中,正则表达式模式包含三个捕获组。我们在新字符串中使用 \1 \2 \3 来引用和替换捕获组捕获的字符串。
如果使用的是命名捕获组,还可以以 \g<name> 的形式引用它们,而不是 \1 或 \2 。请看下面的示例。
import re
msg = 'Product is AE-42'
pattern = re.compile(r'(?P<cate>[A-Z]{2})-(?P<code>[0-9]{2})')
result = pattern.sub(r'Category=\g<cate>/Code=\g<code>', msg)
print(result)
>> Product is Category=AE/Code=42
在此示例中,正则表达式模式包含两个命名的捕获组。在新字符串中,我们使用 \cate 和 \code 来指定一个新字符串,该字符串引用并替换捕获组捕获的字符串。
指定一个函数作为要替换的新字符串
sub 方法(和 sub2 方法)允许您指定一个函数而不是要替换的新字符串。每次进行替换时,都会调用函数并将函数的返回值替换为新值。该函数将在调用时将匹配对象作为参数传递。
请看下面的示例。
import re
msg = 'Border is Red, Box is Green, Line is BLUE'
pattern = re.compile(r'\b[a-zA-Z]+?\b')
def replaceStr(m):
s = m.group(0)
return s.lower()
result = pattern.sub(replaceStr, msg)
print(result)
>> border is red, box is green, line is blue
此示例替换匹配由字母组成的单词的字符串。当模式匹配时,调用该函数,在函数内获取匹配到的字符串,将字符串全部转为小写,作为返回值返回。用作为返回值获得的值替换为新值。结果,字符串中的所有字母单词都已转换为小写。