1. 正则表达式的基本使用
1.1 什么是正则表达式?
正则表达式(Regular Expression)是一种用来匹配字符串的表达式,用来检查一些文本是否符合我们想要的规则。
在 Python 中使用正则表达式需要导入 re 模块:
import re
1.2 定义正则表达式
在正则表达式中,我们可以使用一些特殊字符来代替某些字符或字符串,从而实现对字符串的匹配。
一些常见的特殊字符:
. :匹配任意字符,除了换行符
^ :匹配字符串的开头
$ :匹配字符串的结尾
* :匹配前面的字符出现 0 次或多次
+ :匹配前面的字符出现 1 次或多次
? :匹配前面的字符出现 0 次或 1 次
除此之外,我们还可以使用一些字符类来进行匹配:
\d :匹配数字,等价于 [0-9]
\D :匹配非数字,等价于 [^0-9]
\w :匹配字母、数字、下划线,等价于 [a-zA-Z0-9_]
\W :匹配非字母、数字、下划线,等价于 [^a-zA-Z0-9_]
\s :匹配空白字符,包括空格、制表符、换行符
\S :匹配非空白字符
除此之外,我们还可以使用中括号来指定匹配的字符集合:
# 匹配一个数字
pattern = r"\d"
# 匹配一个小写字母
pattern = r"[a-z]"
1.3 匹配字符串
要在 Python 中使用正则表达式进行字符串匹配,需要使用 re 模块中的 match()、search()、findall()、sub() 等函数。
1.3.1 match() 函数
match() 函数用来检查字符串的开头是否符合某个正则表达式:
pattern = r"\d+"
s = "123ABC"
match_result = re.match(pattern, s)
print(match_result)
输出结果:
<re.Match object; span=(0, 3), match='123'>
match_result 的值是一个 Match 对象,它包含了匹配的结果信息。
如果匹配成功,match_result 就是一个非 None 的值。
1.3.2 search() 函数
search() 函数用来查找字符串中第一个符合正则表达式的子串:
pattern = r"world"
s = "hello world"
search_result = re.search(pattern, s)
print(search_result)
输出结果:
<re.Match object; span=(6, 11), match='world'>
1.3.3 findall() 函数
findall() 函数将返回一个列表,包含字符串中所有与正则表达式匹配的子串:
pattern = r"\d+"
s = "123ABC456DEF789GHI"
findall_result = re.findall(pattern, s)
print(findall_result)
输出结果:
['123', '456', '789']
1.3.4 sub() 函数
sub() 函数用来将字符串中符合正则表达式的子串替换为指定的字符串:
pattern = r"\d+"
s = "123ABC456DEF789GHI"
sub_result = re.sub(pattern, "X", s)
print(sub_result)
输出结果:
XABCXDEFXGHI
1.4 正则表达式的贪婪匹配
正则表达式默认是贪婪匹配的,也就是说它会尽可能多地匹配符合要求的字符串。
例如:
pattern = r"b.+d"
s = "abcdefghijk"
match_result = re.match(pattern, s)
print(match_result)
输出结果:
<re.Match object; span=(1, 6), match='bcdef'>
我们本来希望匹配到的是 "bcd",但是正则表达式却匹配到了更多的字符,这就是贪婪匹配的特点。
1.5 正则表达式的非贪婪匹配
我们可以在正则表达式的量词后面加上一个问号,来实现非贪婪匹配。
例如:
pattern = r"b.+?d"
s = "abcdefghijk"
match_result = re.match(pattern, s)
print(match_result)
输出结果:
<re.Match object; span=(1, 4), match='bcd'>
非贪婪匹配的意思就是尽可能少地匹配符合要求的字符串。
2. 正则表达式的进阶用法
2.1 分组匹配
我们可以使用圆括号来分组匹配,同时可以使用 group() 函数来获取匹配的结果。
例如:
pattern = r"(\d+)-(\d+)-(\d+)"
s = "2022-01-01"
match_result = re.match(pattern, s)
print(match_result.group())
print(match_result.group(1))
print(match_result.group(2))
print(match_result.group(3))
输出结果:
2022-01-01
2022
01
01
在上面的例子中,我们使用圆括号将正则表达式分成了三组,每组都是匹配数字的正则表达式。
执行 group() 函数可以获取到匹配的结果,group(1) 表示获取第一组匹配的结果,以此类推。
2.2 环视匹配
环视匹配是一种非常有用的正则表达式技巧,它可以让我们在不消耗位置的情况下匹配字符串。
环视匹配分为正向环视和负向环视两种:
(?=...) :正向环视,要求被匹配的字符串后面必须匹配 ...,但匹配结果不包含 ...
(?!...) :负向环视,要求被匹配的字符串后面不能匹配 ...,但匹配结果不包含 ...
例如,我们要匹配一个数字后面跟着一个字母,但是不想匹配这个字母,可以使用正向环视:
pattern = r"\d(?=[a-z])"
s1 = "1a"
s2 = "1B"
match_result1 = re.search(pattern, s1)
match_result2 = re.search(pattern, s2)
print(match_result1)
print(match_result2)
输出结果:
<re.Match object; span=(0, 1), match='1'>
None
我们可以看到,第一个字符串中的数字匹配成功了,而第二个字符串中的数字因为后面跟着大写字母而未匹配成功。
2.3 自定义匹配函数
如果我们想要匹配更复杂的字符串,不仅仅可以使用正则表达式。
Python 还提供了一种机制,可以使用函数来自定义匹配逻辑。
使用 re.compile() 函数可以将正则表达式编译为一个 Pattern 对象,然后使用 match()、search()、findall()、sub() 等函数来进行匹配。
此外,我们还需要定义一个函数来处理匹配到的结果,这个函数的参数就是匹配对象。
例如,我们要将字符串中的大写字母替换成相应的小写字母,可以这样实现:
pattern = re.compile(r"[A-Z]")
s = "Hello World"
def repl(match_obj):
return match_obj.group().lower()
new_s = pattern.sub(repl, s)
print(new_s)
输出结果:
hello world
在上面的例子中,我们首先使用 re.compile() 函数将正则表达式编译为一个 Pattern 对象,然后使用 sub() 函数进行字符串替换,而替换逻辑是由我们自己编写的 repl() 函数完成的。
2.4 正则表达式的模式参数
在使用正则表达式时,我们可以使用一些参数来控制匹配的行为。
2.4.1 re.IGNORECASE
这个参数用来控制正则表达式的大小写敏感程度。
pattern = re.compile(r"hello", re.IGNORECASE)
s1 = "Hello World"
s2 = "HELLO WORLD"
match_result1 = pattern.search(s1)
match_result2 = pattern.search(s2)
print(match_result1)
print(match_result2)
输出结果:
<re.Match object; span=(0, 5), match='Hello'>
<re.Match object; span=(0, 5), match='HELLO'>
我们可以看到,虽然正则表达式中匹配的是小写的 "hello",但是由于使用了 re.IGNORECASE 参数,所以可以成功匹配到大写的 "HELLO"。
2.4.2 re.MULTILINE
这个参数用来控制正则表达式的多行匹配。
例如,我们要匹配字符串中所有开头是数字的行:
pattern = re.compile(r"^\d+", re.MULTILINE)
s = "1st line\n2nd line\n3rd line"
match_result = pattern.findall(s)
print(match_result)
输出结果:
['1', '2', '3']
在上面的例子中,我们使用了 re.MULTILINE 参数,这样正则表达式中的 ^ 就匹配行的开头,而不是字符串的开头。
2.4.3 re.DOTALL
这个参数可以让正则表达式中的 . 匹配换行符。
例如:
pattern = re.compile(r"hello.world", re.DOTALL)
s = "hello\nworld"
match_result = pattern.search(s)
print(match_result)
输出结果:
<re.Match object; span=(0, 11), match='hello\nworld'>
我们可以看到,由于使用了 re.DOTALL 参数,所以正则表达式中的 . 可以匹配换行符,因此可以成功匹配到 "hello\nworld"。
3. 小结
正则表达式是一种十分强大的工具,可以用来匹配、查找、替换字符串中的内容。
在 Python 中,我们可以使用 re 模块进行正则表达式的操作。
正则表达式的基本使用包括定义正则表达式、匹配字符串、分组匹配、环视匹配等。
正则表达式的进阶用法包括自定义匹配函数、正则表达式的模式参数等。