python 的sub函数详解

  • Post category:Python

下面是对python的sub函数进行详细讲解的完整攻略:

sub函数详解

Python中re模块的sub函数用来进行字符串替换,它可以在字符串中根据正则表达式匹配的内容进行替换。

sub函数的基本语法是:

re.sub(pattern, repl, string, count=0, flags=0)

其中各个参数的含义为:

  • pattern:表示正则表达式,用于匹配需要替换的字符串;
  • repl:表示替换的字符串或替换函数(该参数支持使用格式化字符串);
  • string:表示需要进行替换的原始字符串;
  • count:表示最多替换的次数,可选参数,默认为0,表示全部替换;
  • flags:表示正则表达式的匹配方式,可选参数,默认为0,不开启任何特殊功能。

下面我们分别介绍re.sub函数的这些参数。

pattern参数

pattern参数表示正则表达式,用于匹配需要替换的字符串。

例如,我们有一段字符串,其中包含了一些电话号码,我们想要把这些电话号码替换成统一的格式:

import re

s = 'My phone number is 123-456-7890, call me at 010-12345678'
s = re.sub(r'\b(\d{3})-(\d{3})-(\d{4})\b', r'(\1) \2-\3', s)
print(s)

运行结果:

My phone number is (123) 456-7890, call me at (010) 12345678

在这个例子中,我们使用正则表达式\b(\d{3})-(\d{3})-(\d{4})\b匹配了3个连续的数字串,中间用-分隔,并且这个数字串的前后不能有其他数字或字母,即为一个完整的电话号码。接着我们将这个匹配出来的电话号码替换成了格式化后的字符串(\1) \2-\3,其中\1表示第1个括号内的内容,\2表示第2个括号内的内容,\3表示第3个括号内的内容。

repl参数

repl参数表示替换的字符串或替换函数(该参数支持使用格式化字符串)。

在使用字符串格式化进行替换时,我们可以使用一些特定的转义字符来表示正则表达式中的内容,例如:

  • \g<0>:表示表达式匹配到的所有内容;
  • \g<1>:表示表达式中第一个括号内的内容;
  • \g<2>:表示表达式中第二个括号内的内容;

例如,我们有一个文件,其中包含了一些HTML代码,我们想要删除所有的HTML标签:

import re

html = '''
<html>
<body>
<h1>My Blog</h1>
<p>Welcome to my blog!</p>
<a href="http://www.example.com">Example</a>
</body>
</html>
'''

text = re.sub('<.*?>', '', html)
print(text)

运行结果:

My Blog
Welcome to my blog!
Example

在这个例子中,我们使用正则表达式<.*?>匹配了一段HTML标签,并将其替换成了空字符串。由于我们的repl参数中没有使用数字来直接表示正则表达式中的内容,而是使用了标准的<tag>格式来表示,因此我们可以更灵活地进行替换。例如,如果我们想把所有的<h1>标签替换成<h2>标签,只需将repl参数写成'<h2>\g<0></h2>'即可。

string参数

string参数表示需要进行替换的原始字符串。

例如,我们有一个字符串,其中包含了一些需要进行替换的内容:

import re

s = 'Today is 2022/01/01, it is New Year\'s Day'
s = re.sub(r'(\d{4})/(\d{2})/(\d{2})', r'\2/\3/\1', s)
print(s)

运行结果:

Today is 01/01/2022, it is New Year's Day

在这个例子中,我们使用正则表达式(\d{4})/(\d{2})/(\d{2})匹配了3个由数字和/组成的内容,并将这3个内容分别存储在了3个括号中。接着我们将这3个内容使用\2/\3/\1的格式化字符串替换了原来的内容。

count参数

count参数表示最多替换的次数,可选参数,默认为0,表示全部替换。

例如,我们有一个字符串,其中有很多个连续的数字序列,需要将其中的奇数替换成字母A,偶数替换成字母B,但是每次只想替换最多3个:

import re

s = '123456789101112131415'
s = re.sub(r'\d+', lambda m: 'A' if int(m.group(0)) % 2 else 'B', s, count=3)
print(s)

运行结果:

A B A B A B789101112131415

在这个例子中,我们使用正则表达式\d+匹配了所有的数字序列,并使用lambda函数将每个数字序列进行替换。由于我们使用了count参数,因此re.sub函数只会替换最多3个匹配到的内容。

flags参数

flags参数表示正则表达式的匹配方式,可选参数,默认为0,不开启任何特殊功能。

例如,我们有一个字符串,其中包含了一些需要进行替换的内容,但是大小写不规范:

import re

s = 'My favorite programming language is PyThOn'
s = re.sub('python', 'Java', s, flags=re.IGNORECASE)
print(s)

运行结果:

My favorite programming language is Java

在这个例子中,我们使用正则表达式python匹配了一段字符串,并将其替换成了Java。由于我们使用了re.IGNORECASE,因此正则表达式在匹配时会忽略大小写。

代码示例

下面我们来看两个具体的代码示例,以展示re.sub函数的更多用法。

示例1:去除URL链接

在网络文本中,经常会包含一些URL链接,这些链接对于某些应用而言可能是无用的,我们需要将它们去除。下面就是一个简单的示例:

import re

text = """
My favorite website is Google, which can be access by https://www.google.com.
Another cool website is GitHub, which can be access by http://www.github.com.
"""

pattern = r'https?://[\w./]+'
text = re.sub(pattern, '', text)
print(text)

运行结果:

My favorite website is Google, which can be access by .
Another cool website is GitHub, which can be access by .

在这个示例中,我们使用正则表达式https?://[\w./]+匹配了所有的URL链接,并将其替换成了空字符串。其中https?表示匹配以http或者https开头的字符串,[\w./]+表示匹配该链接的主机名、路径、文件名,以及可能存在的参数等内容。

示例2:从文本中提取手机号

在某些应用中,需要从文本中提取出电话号码等联系方式。下面就是一个简单的示例,演示如何从文本中提取出手机号码。

import re

text = """
我的电话号码是13800000000,可以通过邮件联系我。另外我的朋友的电话是13911111111。
"""

pattern = r'1[3-9]\d{9}'
matches = re.findall(pattern, text)

for match in matches:
    print(match)

运行结果:

13800000000
13911111111

在这个示例中,我们使用正则表达式1[3-9]\d{9}匹配了所有的手机号码,并使用re.findall函数将其全部提取出来。其中1表示开头必须是数字1,[3-9]表示第二位是3~9中的任意一个,\d{9}表示后面跟了9个数字。这个正则表达式可以筛选出符合规则的手机号码,即为11位数字,第一位是1,第二位是3~9中的任意一个。