Python正则表达式教程展示了如何在Python中使用正则表达式。对于Python中的正则表达式,我们使用re模块。
正则表达式用于文本搜索和更高级的文本操作。正则表达式是内置工具,例如grep、sed、文本编辑器(例如vi、emacs)以及编程语言(例如Tcl、Perl和Python)。
Pythonre模块
在Python中,re
模块提供了正则表达式匹配操作。
模式是一个正则表达式,它定义了我们正在搜索或操作的文本。它由文本文字和元字符组成。该模式是使用compile
函数编译的。因为正则表达式通常包含特殊字符,所以建议使用原始字符串。(原始字符串前面有r个字符。)这样,字符在编译为模式之前不会被解释。
编译模式后,我们可以使用其中一个函数将模式应用于文本字符串。这些函数包括match
、search
、find
和finditer
。
正则表达式
下表显示了一些基本的正则表达式:
正则表达式 | 含义 |
---|---|
. |
匹配任何单个字符。 |
? |
匹配前面的元素一次或根本不匹配. |
+ |
匹配前面的元素一次或多次。 |
* |
匹配前面的元素零次或多次。 |
^ |
匹配字符串中的起始位置。 |
$ |
匹配字符串中的结束位置. |
| |
交替运算符。 |
[abc] |
匹配a或b,或c。 |
[a-c] |
范围;匹配a或b,或c。 |
[^abc] |
否定,匹配除a或b以外的所有内容,或c。 |
\s |
匹配空白字符。 |
code>\w | 匹配一个单词字符;相当于[a-zA-Z_0-9] |
正则表达式函数
我们寻找与正则表达式函数的匹配项。
Function | Description |
---|---|
匹配 |
判断RE是否匹配字符串开头 |
fullmatch |
判断是否RE匹配整个字符串。 |
search |
扫描一个字符串,寻找这个RE所在的任何位置匹配。 |
findall |
查找RE匹配的所有子字符串,并将它们作为列表返回。 |
finditer |
查找RE匹配的所有子字符串,并将它们作为迭代器返回。 |
split |
按RE模式拆分字符串。 |
match
、fullmatch
和search
函数如果成功则返回一个匹配对象。否则,它们返回None
。
匹配函数
如果字符串开头的零个或多个字符与正则表达式模式匹配,则match
函数返回一个匹配对象。
#!/usr/bin/python import re words = ('book', 'bookworm', 'Bible', 'bookish','cookbook', 'bookstore', 'pocketbook') pattern = re.compile(r'book') for word in words: if re.match(pattern, word): print(f'The {word} matches')
在示例中,我们有一个单词元组。编译后的模式将在每个单词中查找“book”字符串。
pattern = re.compile(r'book')
使用compile
函数,我们创建了一个模式。正则表达式是一个原始字符串,由四个普通字符组成。
for word in words: if re.match(pattern, word): print(f'The {word} matches')
我们遍历元组并调用match
函数。它将模式应用到单词上。match
函数在字符串开头有匹配项时返回一个匹配对象。如果没有匹配项则返回None
。
$ ./match_fun.py The book matches The bookworm matches The bookish matches The bookstore matches
元组中的四个单词与模式匹配。请注意,不以“书”字词开头的单词不匹配。为了也包括这些词,我们使用search
功能。
全匹配函数
fullmatch
函数看起来完全匹配。
#!/usr/bin/python import re words = ('book', 'bookworm', 'Bible', 'bookish','cookbook', 'bookstore', 'pocketbook') pattern = re.compile(r'book') for word in words: if re.fullmatch(pattern, word): print(f'The {word} matches')
在示例中,我们使用fullmatch
函数来查找确切的“book”字词。
$ ./fullmatch_fun.py The book matches
只有一个匹配。
搜索功能
search
函数查找正则表达式模式产生匹配项的第一个位置。
#!/usr/bin/python import re words = ('book', 'bookworm', 'Bible', 'bookish','cookbook', 'bookstore', 'pocketbook') pattern = re.compile(r'book') for word in words: if re.search(pattern, word): print(f'The {word} matches')
在示例中,我们使用search
函数来查找“book”字词。
$ ./search_fun.py The book matches The bookworm matches The bookish matches The cookbook matches The bookstore matches The pocketbook matches
这次食谱和钱包单词也包括在内。
点元字符
点(.)元字符代表文本中的任何单个字符。
#!/usr/bin/python import re words = ('seven', 'even', 'prevent', 'revenge', 'maven', 'eleven', 'amen', 'event') pattern = re.compile(r'.even') for word in words: if re.match(pattern, word): print(f'The {word} matches')
在示例中,我们有一个包含八个单词的元组。我们在每个单词上应用包含点元字符的模式。
pattern = re.compile(r'.even')
点代表文本中的任何单个字符。该字符必须存在。
$ ./dot_meta.py The seven matches The revenge matches
两个词符合模式:七和复仇。
问号元字符
问号(?)元字符是与前一个元素零次或一次匹配的量词。
#!/usr/bin/python import re words = ('seven', 'even','prevent', 'revenge', 'maven', 'eleven', 'amen', 'event') pattern = re.compile(r'.?even') for word in words: if re.match(pattern, word): print(f'The {word} matches')
在示例中,我们在点字符后添加了一个问号。这意味着在模式中我们可以有一个任意字符,也可以没有任何字符。
$ ./question_mark_meta.py The seven matches The even matches The revenge matches The event matches
这一次,除了七和复仇之外,even和event的词组也是如此。
锚点
锚匹配给定文本中字符的位置。使用^锚点时,匹配必须出现在字符串的开头,而使用$锚点时,匹配必须出现在字符串的末尾。
#!/usr/bin/python import re sentences = ('I am looking for Jane.', 'Jane was walking along the river.', 'Kate and Jane are close friends.') pattern = re.compile(r'^Jane') for sentence in sentences: if re.search(pattern, sentence): print(sentence)
在示例中,我们有三个句子。搜索模式是^Jane
。该模式检查“Jane”字符串是否位于文本的开头。Jane\.
将在句子末尾查找“Jane”。
精确匹配
可以使用fullmatch
函数或将术语放在锚点之间:^和$来执行精确匹配。
#!/usr/bin/python import re words = ('book', 'bookworm', 'Bible', 'bookish','cookbook', 'bookstore', 'pocketbook') pattern = re.compile(r'^book$') for word in words: if re.search(pattern, word): print(f'The {word} matches')
在示例中,我们寻找与“书”字词完全匹配的词。
$ ./exact_match.py The book matches
字符类
字符类定义了一组字符,其中任何一个字符都可以出现在输入字符串中才能成功匹配。
#!/usr/bin/python import re words = ('a gray bird', 'grey hair', 'great look') pattern = re.compile(r'gr[ea]y') for word in words: if re.search(pattern, word): print(f'{word} matches')
在示例中,我们使用字符类来包含灰色和灰色词。
pattern = re.compile(r'gr[ea]y')
[ea]
类允许在模式中使用’e’或’a’字符。
命名字符类
有一些预定义的字符类。\s
匹配一个空白字符[\t\n\t\f\v]
,\d
匹配一个数字[0-9]
,以及\w
一个单词字符[a-zA-Z0-9_]
。
#!/usr/bin/python import re text = 'We met in 2013. She must be now about 27 years old.' pattern = re.compile(r'\d+') found = re.findall(pattern, text) if found: print(f'There are {len(found)} numbers')
在示例中,我们计算文本中的数字。
pattern = re.compile(r'\d+')
\d+
模式在文本中查找任意数量的数字集。
found = re.findall(pattern, text)
使用findall
方法,我们查找文本中的所有数字。
$ ./named_character_classes.py There are 2 numbers
不区分大小写的匹配
默认情况下,模式的匹配是区分大小写的。通过将re.IGNORECASE
传递给compile
函数,我们可以使其不区分大小写。
#!/usr/bin/python import re words = ('dog', 'Dog', 'DOG', 'Doggy') pattern = re.compile(r'dog', re.IGNORECASE) for word in words: if re.match(pattern, word): print(f'{word} matches')
在示例中,我们将模式应用于单词而不考虑大小写。
$ ./case_insensitive.py dog matches Dog matches DOG matches Doggy matches
所有四个词都匹配模式。
交替
交替运算符|创建一个有多个选项的正则表达式。
#!/usr/bin/python import re words = ("Jane", "Thomas", "Robert", "Lucy", "Beky", "John", "Peter", "Andy") pattern = re.compile(r'Jane|Beky|Robert') for word in words: if re.match(pattern, word): print(word)
列表中有八个名字。
pattern = re.compile(r'Jane|Beky|Robert')
此正则表达式查找“Jane”、“Beky”或“Robert”字符串。
查找器功能
finditer
函数返回一个迭代器,该迭代器为字符串中的模式的所有非重叠匹配生成匹配对象。
#!/usr/bin/python import re text = 'I saw a fox in the wood. The fox had red fur.' pattern = re.compile(r'fox') found = re.finditer(pattern, text) for item in found: s = item.start() e = item.end() print(f'Found {text[s:e]} at {s}:{e}')
在示例中,我们在文本中搜索“fox”一词。我们遍历找到的匹配项的迭代器并打印它们及其索引。
s = item.start() e = item.end()
start
和end
函数分别返回开始和结束索引。
$ ./finditer_fun.py Found fox at 8:11 Found fox at 29:32
捕获组
捕获组是一种将多个字符视为一个单元的方法。它们是通过将字符放在一组圆括号内创建的。例如,(book)是包含“b”、“o”、“o”、“k”字符的单个组。
捕获组技术使我们能够找出字符串中与常规模式匹配的部分。
#!/usr/bin/python import re content = '''<p>The <code>Pattern</code> is a compiled representation of a regular expression.</p>''' pattern = re.compile(r'(</?[a-z]*>)') found = re.findall(pattern, content) for tag in found: print(tag)
代码示例通过捕获一组字符来打印提供的字符串中的所有HTML标记。
found = re.findall(pattern, content)
为了找到所有标签,我们使用findall
方法。
$ ./capturing_groups.py <p> <code> </code> </p>
我们找到了四个HTML标签。
Python正则表达式电子邮件示例
在下面的示例中,我们创建了一个用于检查电子邮件地址的正则表达式模式。
#!/usr/bin/python import re emails = ("luke@gmail.com", "andy@yahoocom", "34234sdfa#2345", "f344@gmail.com") pattern = re.compile(r'^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,18}$') for email in emails: if re.match(pattern, email): print(f'{email} matches') else: print(f'{email} does not match')
这个例子提供了一种可能的解决方案。
pattern = re.compile(r'^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,18}$')
第一个^
和最后一个$
字符提供精确的模式匹配。模式前后不允许有任何字符。邮件分为五个部分。第一部分是本地部分。这通常是公司名称、个人名称或昵称。[a-zA-Z0-9._-]+
列出了所有可能的字符,我们可以在本地部分使用。它们可以使用一次或多次。
第二部分由文字@
字符组成。第三部分是领域部分。它通常是电子邮件提供商的域名,例如Yahoo或Gmail。[a-zA-Z0-9-]+
是一个字符类,提供了可以在域名中使用的所有字符。+
量词允许使用这些字符中的一个或多个。
第四部分是点字符。它前面有转义字符(\)以获得文字点。
最后一部分是顶级域:[a-zA-Z.]{2,18}
。顶级域可以有2到18个字符,例如sk、net、信息、旅行、清洁、旅行保险。最大长度可以是63个字符,但现在大多数域都短于18个字符。还有一个点字符。这是因为一些顶级域有两个部分;例如co.uk。
$ ./emails.py luke@gmail.com matches andy@yahoocom does not match 34234sdfa#2345 does not match f344@gmail.com matches
在本章中,我们介绍了Python中的正则表达式。
阅读Python教程或列出所有Python教程。