Python 正则表达式详解

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 模块进行正则表达式的操作。

正则表达式的基本使用包括定义正则表达式、匹配字符串、分组匹配、环视匹配等。

正则表达式的进阶用法包括自定义匹配函数、正则表达式的模式参数等。

后端开发标签