个性化阅读
专注于IT技术分析

Python正则表达式教程

本文概述

正则表达式用于标识模式是否存在于给定的字符(字符串)序列中。它们有助于处理文本数据, 这通常是涉及文本挖掘的数据科学项目的先决条件。你必须遇到过一些正则表达式的应用程序:它们在服务器端用于在注册过程中验证电子邮件地址或密码的格式, 用于解析文本数据文件以查找, 替换或删除某些字符串等。

你会看到, 正则表达式非常强大, 在本教程中, 你将学习在Python中使用它们。你将涵盖以下主题:

  • Python中的正则表达式
  • 基本字符:普通字符
  • 通配符:特殊字符
  • 重复次数
  • 使用正则表达式进行分组和分组
  • 贪婪vs非贪婪匹配
  • Python re库
    • search()与match()

查看srcmini的自然语言处理基础课程。本课程将在解决常见的NLP问题的背景下更深入地使用正则表达式。你将建立一个监督学习分类器, 以识别”假新闻”。请务必尝试一下, 第一章是免费的!

Python中的正则表达式

在Python中, re模块支持正则表达式。这意味着, 如果要开始在Python脚本中使用它们, 则必须在import的帮助下导入此模块:

基本模式:普通字符

你可以使用普通字符轻松解决Python中的许多基本模式。普通字符是最简单的正则表达式。它们完全匹配, 并且在正则表达式语法中没有特殊含义。

示例为” A”, ” a”, ” X”, ” 5″。

普通字符可用于执行简单的完全匹配:

如果文本与模式匹配, 则match()函数将返回匹配对象。否则, 它返回None。 re模块还包含其他一些功能, 你将在本教程的后面部分中学习其中的一些功能。

不过, 现在让我们关注普通字符!你是否注意到模式Cookie开头的r?

这称为原始字符串文字。它更改了字符串文字的解释方式。这样的文字按其出现时存储。

例如, \只是带有r的反斜杠, 而不是被解释为转义序列。你将看到特殊字符的含义。有时, 语法涉及反斜杠转义的字符, 并且为了防止将这些字符解释为转义序列, 请使用原始r前缀。在本示例中, 你实际上并不需要它, 但是使用它来保持一致性是一种很好的做法。

通配符:特殊字符

特殊字符是指与正则表达式不匹配但在正则表达式中使用时实际上具有特殊含义的字符。

最广泛使用的特殊字符是:

  • 。 – 一段时间。匹配除换行符以外的任何单个字符。
re.search(r'Co.k.e', 'Cookie').group()
'Cookie'

group()函数返回与re匹配的字符串。稍后你将更详细地看到此功能。

  • \ w-小写字母w。匹配任何单个字母, 数字或下划线。
re.search(r'Co\wk\we', 'Cookie').group()
'Cookie'
  • \ W-大写w。匹配不属于\ w的任何字符(小写w)。
re.search(r'C\Wke', 'C@ke').group()
'C@ke'
  • \ s-小写字母s。匹配单个空格字符, 例如:空格, 换行符, 制表符, 返回值。
re.search(r'Eat\scake', 'Eat cake').group()
'Eat cake'
  • \ S-大写s。匹配不属于\ s的任何字符(小写s)。
re.search(r'Cook\Se', 'Cookie').group()
'Cookie'
  • \ t-小写字母t。匹配标签。
re.search(r'Eat\tcake', 'Eat    cake').group()
'Eat\tcake'
  • \ n-小写字母n。匹配换行符。
  • \ r-小写字母r。比赛归来。
  • \ d-小写字母d。匹配十进制数字0-9。
re.search(r'c\d\dkie', 'c00kie').group()
'c00kie'
  • ^-插入符号。在字符串的开头匹配一个模式。
re.search(r'^Eat', 'Eat cake').group()
'Eat'
  • $-匹配字符串末尾的模式。
re.search(r'cake$', 'Eat cake').group()
'cake'
  • [abc]-匹配a或b或c。
  • [a-zA-Z0-9]-匹配(a至z)或(A至Z)或(0至9)中的任何字母。可以通过补充集合来匹配不在范围内的字符。如果集合的第一个字符是^, 则所有不在集合中的字符都将被匹配。
re.search(r'Number: [0-6]', 'Number: 5').group()
'Number: 5'
# Matches any character except 5
re.search(r'Number: [^5]', 'Number: 0').group()
'Number: 0'
  • \ A-大写a。仅在字符串开头匹配。也可以跨多行工作。
re.search(r'\A[A-E]ookie', 'Cookie').group()
'Cookie'
  • \ b-小写字母b。仅匹配单词的开头或结尾。
re.search(r'\b[A-E]ookie', 'Cookie').group()
'Cookie'
  • \-反斜杠。如果反斜杠后面的字符是公认的转义字符, 则采用该术语的特殊含义。例如, \ n被视为换行符。但是, 如果\后面的字符不是公认的转义字符, 则\会像其他任何字符一样被处理并传递。

让我们看几个例子:

# This checks for '\' in the string instead of '\t' due to the '\' used 
re.search(r'Back\\stail', 'Back\stail').group()
'Back\\stail'
# This treats '\s' as an escape character because it lacks '\' at the start of '\s'
re.search(r'Back\stail', 'Back tail').group()
'Back lash'

重复次数

如果你要查找序列中的长模式, 将变得非常乏味。幸运的是, re模块使用以下特殊字符处理重复:

  • +-检查其左侧的一个或多个字符。
re.search(r'Co+kie', 'Cooookie').group()
'Cooookie'
  • *-检查左侧的零个或多个字符。
# Checks for any occurrence of a or o or both in the given sequence
re.search(r'Ca*o*kie', 'Caokie').group()
'Caokie'
  • ? -检查其左边是否为零或一个字符。
# Checks for exactly zero or one occurrence of a or o or both in the given sequence
re.search(r'Colou?r', 'Color').group()
'Color'

但是, 如果你要检查序列重复的确切数目怎么办?

例如, 检查应用程序中电话号码的有效性。 re模块也使用以下正则表达式很好地处理了此问题:

{x}-精确重复x次。

{x, }-重复至少x次或更多。

{x, y}-重复至少x次, 但不超过y次。

re.search(r'\d{9, 10}', '0987654321').group()
'0987654321'

+和*限定词被认为是贪婪的。

使用正则表达式进行分组和分组

假设当你验证电子邮件地址并想要分别检查用户名和主机时, 请执行以下操作。

这是正则表达式的分组功能派上用场的时候。它允许你拾取匹配文本的一部分。

由括号()界定的正则表达式模式的一部分称为组。括号不会更改表达式匹配的内容, 而是会在匹配的序列中形成组。在本教程的示例中, 你一直都在使用group()函数。没有任何参数的简单match.group()仍然是整个匹配的文本, 照常。

贪婪vs非贪婪匹配

当特殊字符与搜索序列(字符串)尽可能匹配时, 则称为”贪婪匹配”。这是正则表达式的正常行为, 但有时不希望出现这种行为:

pattern = "cookie"
sequence = "Cake and cookie"

heading  = r'<h1>TITLE</h1>'
re.match(r'<.*>', heading).group()
'<h1>TITLE</h1>'

模式<。*>匹配整个字符串, 直到第二次出现>为止。

但是, 如果只想匹配第一个<h1>标记, 则可以使用贪婪的限定符*?匹配的文字越少越好。

加上?限定符使其以非贪婪或最小的方式执行比赛之后;即, 将匹配尽可能少的字符。运行<。*>时, 只会得到与<h1>匹配的内容。

heading  = r'<h1>TITLE</h1>'
re.match(r'<.*?>', heading).group()
'<h1>'

Python re库

Python中的re库提供了几个函数, 使其值得掌握。你已经看过其中的一些, 例如re.search(), re.match()。让我们详细检查一些有用的功能:

  • 搜索(模式, 字符串, 标志= 0)

使用此功能, 你可以浏览给定的字符串/序列, 以查找正则表达式产生匹配项的第一个位置。如果找到, 它将返回一个对应的匹配对象;否则, 如果字符串中的任何位置都不匹配该模式, 则返回None。请注意, None与在字符串中的某个点找到零长度匹配不同。

pattern = "cookie"
sequence = "Cake and cookie"

re.search(pattern, sequence).group()
'cookie'
  • 匹配(模式, 字符串, 标志= 0)

如果字符串开头的零个或多个字符与模式匹配, 则返回相应的匹配对象。否则, 如果字符串与给定的模式不匹配, 则返回None。

pattern = "C"
sequence1 = "IceCream"

# No match since "C" is not at the start of "IceCream"
re.match(pattern, sequence1)
sequence2 = "Cake"

re.match(pattern, sequence2).group()
'C'

search()与match()

match()函数仅在字符串的开头检查匹配(默认情况下), 而search()函数在字符串的任何位置检查匹配。

  • findall(模式, 字符串, 标志= 0)

查找整个序列中的所有可能匹配项, 并将它们作为字符串列表返回。每个返回的字符串代表一个匹配项。

email_address = "Please contact us at: support@srcmini02.com, xyz@srcmini02.com"

#'addresses' is a list that stores all the possible match
addresses = re.findall(r'[\w\.-]+@[\w\.-]+', email_address)
for address in addresses: 
    print(address)
support@srcmini02.com
xyz@srcmini02.com
  • 子(模式, REPL, 字符串, 计数= 0, 标志= 0)

这是替代功能。它返回通过用替换repl替换或替换字符串中最左边的非重叠模式所获得的字符串。如果找不到该模式, 则该字符串将原样返回。

email_address = "Please contact us at: xyz@srcmini02.com"
new_email_address = re.sub(r'([\w\.-]+)@([\w\.-]+)', r'support@srcmini02.com', email_address)
print(new_email_address)
Please contact us at: support@srcmini02.com
  • 编译(模式, 标志= 0)

将正则表达式模式编译为正则表达式对象。当你需要在单个程序中多次使用表达式时, 使用compile()函数保存生成的正则表达式对象以供重用会更有效。这是因为缓存了传递给compile()的最新模式的编译版本以及模块级匹配函数。

pattern = re.compile(r"cookie")
sequence = "Cake and cookie"
pattern.search(sequence).group()
'cookie'
# This is equivalent to:
re.search(pattern, sequence).group()
'cookie'

提示:可以通过指定标志值来修改表达式的行为。你可以将flag作为附加参数添加到本教程中看到的各种函数中。使用的一些标志是:IGNORECASE, DOTALL, MULTILINE, VERBOSE等。

案例研究:使用正则表达式

通过学习一些示例, 你已经了解了正则表达式在Python中的工作方式, 是时候动手了!在本案例研究中, 你将运用自己的知识。

import re
import requests
the_idiot_url = 'https://www.gutenberg.org/files/2638/2638-0.txt'

def get_book(url):
    # Sends a http request to get the text from project Gutenberg
    raw = requests.get(url).text
    # Discards the metadata from the beginning of the book
    start = re.search(r"\*\*\* START OF THIS PROJECT GUTENBERG EBOOK .* \*\*\*", raw ).end()
    # Discards the metadata from the end of the book
    stop = re.search(r"II", raw).start()
    # Keeps the relevant text
    text = raw[start:stop]
    return text

def preprocess(sentence): 
    return re.sub('[^A-Za-z0-9.]+' , ' ', sentence).lower()

book = get_book(the_idiot_url)
processed_book = preprocess(book)
print(processed_book)

在语料库中找到代词” the”的编号。提示:使用len()函数。

len(re.findall(r'the', processed_book))
302

尝试将语料库中的每个” i”的独立实例转换为” I”。确保不要更改一个单词中出现的” i”:

processed_book = re.sub(r'\si\s', " I ", processed_book)
print(processed_book)

查找语料库中有人被引号(“”)的次数。

len(re.findall(r'\"', book))
96

语料中”-“连接的词是什么?

re.findall(r'[a-zA-Z0-9]*--[a-zA-Z0-9]*', book)
['ironical--it', 'malicious--smile', 'fur--or', 'astrachan--overcoat', 'it--the', 'Italy--was', 'malady--a', 'money--and', 'little--to', 'No--Mr', 'is--where', 'I--I', 'I--', '--though', 'crime--we', 'or--judge', 'gaiters--still', '--if', 'through--well', 'say--through', 'however--and', 'Epanchin--oh', 'too--at', 'was--and', 'Andreevitch--that', 'everyone--that', 'reduce--or', 'raise--to', 'listen--and', 'history--but', 'individual--one', 'yes--I', 'but--', 't--not', 'me--then', 'perhaps--', 'Yes--those', 'me--is', 'servility--if', 'Rogojin--hereditary', 'citizen--who', 'least--goodness', 'memory--but', 'latter--since', 'Rogojin--hung', 'him--I', 'anything--she', 'old--and', 'you--scarecrow', 'certainly--certainly', 'father--I', 'Barashkoff--I', 'see--and', 'everything--Lebedeff', 'about--he', 'now--I', 'Lihachof--', 'Zaleshoff--looking', 'old--fifty', 'so--and', 'this--do', 'day--not', 'that--', 'do--by', 'know--my', 'illness--I', 'well--here', 'fellow--you']

这只是一个划痕!

恭喜你!你已经到了Python正则表达式教程的结尾!使用Python, 在你的数据科学之旅中还有更多内容要讲。

正则表达式可以在数据预处理阶段发挥重要作用。在Python课程中查看srcmini的清洁数据。本课程教你如何整理和清理数据以进行数据分析, 从而更好地浏览数据。最后还包括一个案例研究, 你可以在其中使用自己的知识。

赞(0)
未经允许不得转载:srcmini » Python正则表达式教程

评论 抢沙发

评论前必须登录!