原文: http://zetcode.com/python/regularexpressions/

Python 正则表达式教程展示了如何在 Python 中使用正则表达式。 对于 Python 中的正则表达式,我们使用re模块。

正则表达式用于文本搜索和更高级的文本操作。 正则表达式是内置工具,如grepsed,文本编辑器(如 vi,emacs),编程语言(如 Tcl,Perl 和 Python)。

Python re模块

在 Python 中,re模块提供了正则表达式匹配操作。

模式是一个正则表达式,用于定义我们正在搜索或操纵的文本。 它由文本文字和元字符组成。 用compile()函数编译该模式。 由于正则表达式通常包含特殊字符,因此建议使用原始字符串。 (原始字符串以r字符开头。)这样,在将字符编译为模式之前,不会对这些字符进行解释。

编译模式后,可以使用其中一个函数将模式应用于文本字符串。 函数包括match()search()find()finditer()

下表显示了一些正则表达式:

正则表达式 含义
. 匹配任何单个字符。
? 一次匹配或根本不匹配前面的元素。
+ 与前面的元素匹配一次或多次。
* 与前面的元素匹配零次或多次。
^ 匹配字符串中的起始位置。
$ 匹配字符串中的结束位置。
` ` 备用运算符。
[abc] 匹配abc
[a-c] 范围; 匹配abc
[^abc] 否定,匹配除abc之外的所有内容。
\s 匹配空白字符。
\w 匹配单词字符; 等同于[a-zA-Z_0-9]

匹配函数

以下是一个代码示例,演示了 Python 中简单正则表达式的用法。

match_fun.py

  1. #!/usr/bin/python3
  2. import re
  3. words = ('book', 'bookworm', 'Bible',
  4. 'bookish','cookbook', 'bookstore', 'pocketbook')
  5. pattern = re.compile(r'book')
  6. for word in words:
  7. if re.match(pattern, word):
  8. print('The {} matches '.format(word))

在示例中,我们有一个单词元组。 编译后的模式将在每个单词中寻找一个"book"字符串。

  1. pattern = re.compile(r'book')

使用compile()函数,我们可以创建模式串。 正则表达式是一个原始字符串,由四个普通字符组成。

  1. for word in words:
  2. if re.match(pattern, word):
  3. print('The {} matches '.format(word))

我们遍历元组并调用match()函数。 它将模式应用于单词。 如果字符串开头有匹配项,则match()函数将返回匹配对象。

  1. $ ./match_fun.py
  2. The book matches
  3. The bookworm matches
  4. The bookish matches
  5. The bookstore matches

元组中的四个单词与模式匹配。 请注意,以"book"一词开头的单词不匹配。 为了包括这些词,我们使用search()函数。

搜索函数

search()函数查找正则表达式模式产生匹配项的第一个位置。

search_fun.py

  1. #!/usr/bin/python3
  2. import re
  3. words = ('book', 'bookworm', 'Bible',
  4. 'bookish','cookbook', 'bookstore', 'pocketbook')
  5. pattern = re.compile(r'book')
  6. for word in words:
  7. if re.search(pattern, word):
  8. print('The {} matches '.format(word))

在示例中,我们使用search()函数查找"book"一词。

  1. $ ./search_fun.py
  2. The book matches
  3. The bookworm matches
  4. The bookish matches
  5. The cookbook matches
  6. The bookstore matches
  7. The pocketbook matches

这次还包括菜谱和袖珍书中的单词。

点元字符

点(。)元字符代表文本中的任何单个字符。

dot_meta.py

  1. #!/usr/bin/python3
  2. import re
  3. words = ('seven', 'even', 'prevent', 'revenge', 'maven',
  4. 'eleven', 'amen', 'event')
  5. pattern = re.compile(r'.even')
  6. for word in words:
  7. if re.match(pattern, word):
  8. print('The {} matches '.format(word))

在示例中,我们有一个带有八个单词的元组。 我们在每个单词上应用一个包含点元字符的模式。

  1. pattern = re.compile(r'.even')

点代表文本中的任何单个字符。 字符必须存在。

  1. $ ./dot_meta.py
  2. The seven matches
  3. The revenge matches

两个字匹配模式:七个和复仇。

问号元字符

问号(?)元字符是与上一个元素零或一次匹配的量词。

question_mark_meta.py

  1. #!/usr/bin/python3
  2. import re
  3. words = ('seven', 'even','prevent', 'revenge', 'maven',
  4. 'eleven', 'amen', 'event')
  5. pattern = re.compile(r'.?even')
  6. for word in words:
  7. if re.match(pattern, word):
  8. print('The {} matches '.format(word))

在示例中,我们在点字符后添加问号。 这意味着在模式中我们可以有一个任意字符,也可以在那里没有任何字符。

  1. $ ./question_mark_meta.py
  2. The seven matches
  3. The even matches
  4. The revenge matches
  5. The event matches

这次,除了七个和复仇外,偶数和事件词也匹配。

锚点

锚点匹配给定文本内字符的位置。 当使用^锚时,匹配必须发生在字符串的开头,而当使用$锚时,匹配必须发生在字符串的结尾。

anchors.py

  1. #!/usr/bin/python3
  2. import re
  3. sentences = ('I am looking for Jane.',
  4. 'Jane was walking along the river.',
  5. 'Kate and Jane are close friends.')
  6. pattern = re.compile(r'^Jane')
  7. for sentence in sentences:
  8. if re.search(pattern, sentence):
  9. print(sentence)

在示例中,我们有三个句子。 搜索模式为^Jane。 该模式检查"Jane"字符串是否位于文本的开头。 Jane\.将在句子结尾处查找"Jane"

fullmatch

可以使用fullmatch()函数或通过将术语放在锚点之间来进行精确匹配:^和$。

exact_match.py

  1. #!/usr/bin/python3
  2. import re
  3. words = ('book', 'bookworm', 'Bible',
  4. 'bookish','cookbook', 'bookstore', 'pocketbook')
  5. pattern = re.compile(r'^book$')
  6. for word in words:
  7. if re.search(pattern, word):
  8. print('The {} matches'.format(word))

在示例中,我们寻找与"book"一词完全匹配的内容。

  1. $ ./exact_match.py
  2. The book matches

这是输出。

字符类

字符类定义了一组字符,任何字符都可以出现在输入字符串中以使匹配成功。

character_class.py

  1. #!/usr/bin/python3
  2. import re
  3. words = ('a gray bird', 'grey hair', 'great look')
  4. pattern = re.compile(r'gr[ea]y')
  5. for word in words:
  6. if re.search(pattern, word):
  7. print('{} matches'.format(word))

在该示例中,我们使用字符类同时包含灰色和灰色单词。

  1. pattern = re.compile(r'gr[ea]y')

[ea]类允许在模式中使用’e’或’a’字符。

命名字符类

有一些预定义的字符类。 \s与空白字符[\t\n\t\f\v]匹配,\d与数字[0-9]匹配,\w与单词字符[a-zA-Z0-9_]匹配。

named_character_class.py

  1. #!/usr/bin/python3
  2. import re
  3. text = 'We met in 2013\. She must be now about 27 years old.'
  4. pattern = re.compile(r'\d+')
  5. found = re.findall(pattern, text)
  6. if found:
  7. print('There are {} numbers'.format(len(found)))

在示例中,我们计算文本中的数字。

  1. pattern = re.compile(r'\d+')

\d+模式在文本中查找任意数量的数字集。

  1. found = re.findall(pattern, text)

使用findall()方法,我们可以查找文本中的所有数字。

  1. $ ./named_character_classes.py
  2. There are 2 numbers

这是输出。

不区分大小写的匹配

默认情况下,模式匹配区分大小写。 通过将re.IGNORECASE传递给compile()函数,我们可以使其不区分大小写。

case_insensitive.py

  1. #!/usr/bin/python3
  2. import re
  3. words = ('dog', 'Dog', 'DOG', 'Doggy')
  4. pattern = re.compile(r'dog', re.IGNORECASE)
  5. for word in words:
  6. if re.match(pattern, word):
  7. print('{} matches'.format(word))

在示例中,无论大小写如何,我们都将模式应用于单词。

  1. $ ./case_insensitive.py
  2. dog matches
  3. Dog matches
  4. DOG matches
  5. Doggy matches

所有四个单词都与模式匹配。

交替

交替运算符|创建具有多种选择的正则表达式。

alternations.py

  1. #!/usr/bin/python3
  2. import re
  3. words = ("Jane", "Thomas", "Robert",
  4. "Lucy", "Beky", "John", "Peter", "Andy")
  5. pattern = re.compile(r'Jane|Beky|Robert')
  6. for word in words:
  7. if re.match(pattern, word):
  8. print(word)

列表中有八个名称。

  1. pattern = re.compile(r'Jane|Beky|Robert')

此正则表达式查找Jane"Beky""Robert"字符串。

查找方法

finditer()方法返回一个迭代器,该迭代器在字符串中的模式的所有不重叠匹配上产生匹配对象。

find_iter.py

  1. #!/usr/bin/python3
  2. import re
  3. text = ('I saw a fox in the wood. The fox had red fur.')
  4. pattern = re.compile(r'fox')
  5. found = re.finditer(pattern, text)
  6. for item in found:
  7. s = item.start()
  8. e = item.end()
  9. print('Found {} at {}:{}'.format(text[s:e], s, e))

在示例中,我们在文本中搜索"fox"一词。 我们遍历找到的匹配项的迭代器,并使用它们的索引进行打印。

  1. s = item.start()
  2. e = item.end()

start()end()方法分别返回起始索引和结束索引。

  1. $ ./find_iter.py
  2. Found fox at 8:11
  3. Found fox at 29:32

这是输出。

捕获组

捕获组是一种将多个字符视为一个单元的方法。 通过将字符放置在一组圆括号内来创建它们。 例如,(book)是包含'b', 'o', 'o', 'k'字符的单个组。

捕获组技术使我们能够找出字符串中与常规模式匹配的那些部分。

capturing_groups.py

  1. #!/usr/bin/python3
  2. import re
  3. content = '''<p>The <code>Pattern</code> is a compiled
  4. representation of a regular expression.</p>'''
  5. pattern = re.compile(r'(</?[a-z]*>)')
  6. found = re.findall(pattern, content)
  7. for tag in found:
  8. print(tag)

该代码示例通过捕获一组字符来打印提供的字符串中的所有 HTML 标签。

  1. found = re.findall(pattern, content)

为了找到所有标签,我们使用findall()方法。

  1. $ ./capturing_groups.py
  2. <p>
  3. <code>
  4. </code>
  5. </p>

我们找到了四个 HTML 标签。

Python 正则表达式电子邮件示例

在以下示例中,我们创建一个用于检查电子邮件地址的正则表达式模式。

emails.py

  1. #!/usr/bin/python3
  2. import re
  3. emails = ("luke@gmail.com", "andy@yahoocom",
  4. "34234sdfa#2345", "f344@gmail.com")
  5. pattern = re.compile(r'^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\.[a-zA-Z.]{2,18}$')
  6. for email in emails:
  7. if re.match(pattern, email):
  8. print("{} matches".format(email))
  9. else:
  10. print("{} does not match".format(email))

本示例提供了一种可能的解决方案。

  1. 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, info, travel, cleaning, travelinsurance。 最大长度可以为 63 个字符,但是今天大多数域都少于 18 个字符。 还有一个点字符。 这是因为某些顶级域包含两个部分: 例如co.uk

  1. $ ./emails.py
  2. luke@gmail.com matches
  3. andy@yahoocom does not match
  4. 34234sdfa#2345 does not match
  5. f344@gmail.com matches

这是输出。

在本章中,我们介绍了 Python 中的正则表达式。

您可能也对以下相关教程感兴趣: Python CSV 教程Python 教程