Python 中的正则表达式

2023-09-17 22:15:41

术语Regular Expression通常缩写为正则表达式。正则表达式是定义搜索模式的字符序列,主要用于在搜索引擎和文本处理器中执行查找和替换操作。

Python 通过捆绑为标准库一部分的 re 模块提供正则表达式功能。

原始字符串

Python re模块中的不同函数使用原始字符串作为参数。一个普通的string,当前缀为"r"或"R"时,变成一个原始字符串。

rawstr = r'Hello! How are you?'
print(rawstr)  #Hello! How are you?

普通字符串和原始字符串之间的区别在于,函数print()普通字符串翻译转义字符(如有n 等),而原始字符串中的转义字符则不然。

str1 = "Hello!nHow are you?"
print("normal string:", str1)
str2 = r"Hello!nHow are you?"
print("raw string:",str2) 

输出:

normal string: Hello!
How are you?
raw string: Hello!nHow are you?

在上面的示例中,str1内部的n(普通字符串)已转换为在下一行中打印的换行符。 但是,它以str2打印为n - 原始字符串。

元字符

某些字符在显示为零件模式匹配字符串时具有特殊含义。在 Windows 或 Linux DOS 命令中,我们使用 * 和 ?- 它们类似于元字符。Python 的 re 模块使用以下字符作为元字符:

. ^ $ * + ? [ ] | ( )

当一组字母数字字符放在方括号内时,目标字符串[]匹配。 可以在方括号中列出一系列字符或单个字符。例如:

Pattern描述
[abc]匹配任何字符 A、B 或 C
[a-c]它使用范围来表示同一组字符。
[a-z]仅匹配小写字母。
[0-9]仅匹配数字。

以下特定字符具有某些特定含义。

Pattern描述
d匹配任何十进制数字;这等效于类 [0-9]。
D匹配任何非数字字符
s匹配任何空格字符
S匹配任何非空格字符
w匹配任何字母数字字符
W匹配任何非字母数字字符。
.与除换行符" "以外的任何单个字符匹配。
?将模式的出现次数匹配到其左侧的 0 或 1
+次 模式在其左侧出现 1 次或多次
*模式在其左侧出现 0 次或多次
b单词和非单词之间的边界。/B 与/b 相反
[..]匹配方括号中的任何单个字符
它用于特殊含义的字符,如 . 以匹配句点或 + 表示加号。
{n,m}匹配前面的至少 n 次和最多 m 次
a| b匹配 a 或 b

re.match() function

模块re此函数尝试查找给定字符串的开头是否存在指定的模式。

re.match(pattern, string)

如果给定的模式不在开头,则该函数返回 None,如果找到匹配对象,则返回匹配对象。

from re import match
mystr = "Welcome to python114.com"
obj1 = match("We", mystr)
print(obj1)
obj2 = match("teacher", mystr)
print(obj2) 
print("start:", obj1.start(), "end:", obj1.end())

匹配对象具有startend属性。

输出:

<re.Match object; span=(0, 2), match='We'>
None
start: 0 end: 2

下面的示例演示如何使用字符范围来确定字符串是否以"W"开头,后跟字母表。

from re import match
strings=["Welcome to python114.com", "weather forecast","Winston Churchill", "W.G.Grace","Wonders of India", "Water park"]
for string in strings:
    obj = match("W[a-z]",string)
    print(obj)

输出:

<re.Match object; span=(0, 2), match='We'>
None
<re.Match object; span=(0, 2), match='Wi'>
None
<re.Match object; span=(0, 2), match='Wo'>
<re.Match object; span=(0, 2), match='Wa'>

re.search() function

re.search() 函数在给定字符串中的任何位置搜索指定的模式,并在第一次出现时停止搜索。

from re import search
string = "Try to earn while you learn"
obj = search("earn", string)
print(obj)
print(obj.start(), obj.end(), obj.group())  

输出:

<re.Match object; span=(7, 11), match='earn'>
7 11 earn

此函数还返回具有 start 和 end 属性的 Match 对象。它还给出了一组字符,模式是其中的一部分。

re.findall() function

search() 函数相反,findall() 继续搜索模式,直到目标字符串用尽。该对象返回所有匹配项的列表。

from re import findall
string = "Try to earn while you learn"
obj = findall("earn", string)
print(obj)

输出:

['earn', 'earn']

此函数可用于获取句子中的单词列表。我们将使用 W* 模式来实现此目的。我们还检查哪些单词中没有任何元音。

from re import findall, search
obj = findall(r"w*", "Fly in the sky.")
print(obj)
for word in obj:
  obj = search(r"[aeiou]",word)
  if word!='' and obj==None:
    print(word)

输出:

['Fly', '', 'in', '', 'the', '', 'sky', '', '']
Fly
sky

re.finditer() function

re.finditer()函数返回目标字符串中所有匹配项的迭代器对象。对于每个匹配的组,可以通过 span() 属性获得开始和结束位置。

from re import finditer
string = "Try to earn while you learn"
it = finditer("earn", string)
for match in it:
    print(match.span())

输出:

(7, 11)
(23, 27)

re.split() function

re.split()函数的工作方式类似于 Python 中str对象的split()方法。 每次找到空格时,它都会拆分给定的字符串。在上面的findall()获取所有单词的示例中,该列表还包含每个出现的空格作为单词。 这被re模块中的split()函数所消除。

from re import split
string = "Flat is better than nested. Sparse is better than dense."
words = split(r' ', string)
print(words)

输出:

['Flat', 'is', 'better', 'than', 'nested.', 'Sparse', 'is', 'better', 'than', 'dense.']

re.compile() function

re.compile()函数返回一个模式对象,该对象可以在不同的正则表达式函数中重复使用。在下面的示例中,编译字符串 'is' 以获取模式对象,并受制于 search() 方法。

from re import *
pattern = compile(r'[aeiou]')
string = "Flat is better than nested. Sparse is better than dense."
words = split(r' ', string) 
for word in words:
    print(word, pattern.match(word))

output

Flat None
is <re.Match object; span=(0, 1), match='i'>
better None
than None
nested. None
Sparse None
is <re.Match object; span=(0, 1), match='i'>
better None
than None
dense. None

相同的模式对象可以在搜索具有元音的单词时重复使用,如下所示。

for word in words:
    print(word, pattern.search(word))

输出:

Flat <re.Match object; span=(2, 3), match='a'>
is <re.Match object; span=(0, 1), match='i'>
better <re.Match object; span=(1, 2), match='e'>
than <re.Match object; span=(2, 3), match='a'>
nested. <re.Match object; span=(1, 2), match='e'>
Sparse <re.Match object; span=(2, 3), match='a'>
is <re.Match object; span=(0, 1), match='i'>
better <re.Match object; span=(1, 2), match='e'>
than <re.Match object; span=(2, 3), match='a'>
dense. <re.Match object; span=(1, 2), match='e'>