course-nlp——4-regex

本文参考自https://github.com/fastai/course-nlp

正则表达式

在本课中,我们将学习 NLP 工具包中的一个有用工具:正则表达式。
让我们考虑两个激励性的例子:

  1. 电话号码问题
    假设我们得到了一些包含电话号码的数据:
    123-456-7890
    123 456 7890
    101 Howard
    一些电话号码的格式不同(有连字符、无连字符)。此外,数据中还存在一些错误——101 Howard 不是电话号码!我们如何找到所有电话号码?
  2. 创建我们自己的标记
    在之前的课程中,我们使用 sklearn 或 fastai 来标记我们的文本。如果我们想自己做呢?

电话号码问题

假设我们获得了一些包含电话号码的数据:
123-456-7890
123 456 7890
(123)456-7890
101 Howard
一些电话号码的格式不同(连字符、无连字符、括号)。此外,数据中还存在一些错误——101 Howard 不是电话号码!我们如何才能找到所有电话号码?
我们将尝试不使用正则表达式,但会发现这很快会导致大量 if/else 分支语句,并且不是一种很有前途的方法:

尝试 1(不使用正则表达式)

phone1 = "123-456-7890"

phone2 = "123 456 7890"

not_phone1 = "101 Howard"
import string
string.digits
'0123456789'
def check_phone(inp):
    valid_chars = string.digits + ' -()'
    for char in inp:
        if char not in valid_chars:
            return False
    return True
assert(check_phone(phone1))
assert(check_phone(phone2))
assert(not check_phone(not_phone1))

尝试 2(不使用正则表达式)

not_phone2 = "1234"
assert(not check_phone(not_phone2))
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[7], line 1
----> 1 assert(not check_phone(not_phone2))

AssertionError: 
def check_phone(inp):
    nums = string.digits
    valid_chars = nums + ' -()'
    num_counter = 0
    for char in inp:
        if char not in valid_chars:
            return False
        if char in nums:
            num_counter += 1
    if num_counter==10:
        return True
    else:
        return False
assert(check_phone(phone1))
assert(check_phone(phone2))
assert(not check_phone(not_phone1))
assert(not check_phone(not_phone2))

尝试 3(不使用正则表达式)

但我们还需要提取数字!
还有,那怎么办:
34!NA5098gn#213ee2

not_phone3 = "34 50 98 21 32"

assert(not check_phone(not_phone3))
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[8], line 3
      1 not_phone3 = "34 50 98 21 32"
----> 3 assert(not check_phone(not_phone3))

AssertionError:
not_phone4 = "(34)(50)()()982132"

assert(not check_phone(not_phone3))
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[9], line 3
      1 not_phone4 = "(34)(50)()()982132"
----> 3 assert(not check_phone(not_phone3))

AssertionError: 

这变得越来越难以处理。我们需要一种不同的方法。

正则表达式简介

什么是正则表达式?

正则表达式是一种模式匹配语言。
您可以写 [0-9] 或 \d,而不是 0 1 2 3 4 5 6 7 8 9
它是领域特定语言 (DSL)。功能强大(但语言有限)。
您还了解哪些其他 DSL?

  • SQL
  • Markdown
  • TensorFlow

匹配电话号码(正则表达式的“Hello, world!”)

[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9] 匹配美国电话号码。

重构:\d\d\d-\d\d\d-\d\d\d\d

元字符是一个或多个具有独特含义的特殊字符,不用作搜索表达式中的文字。例如,“\d”表示任何数字。

元字符是正则表达式的特别之处。

量词

允许您指定前面的表达式应匹配多少次。
{} 是提取限定符
重构:\d{3}-\d{3}-\d{4}

不精确量词

  1. ? 问号 - 零个或一个
    • 星号 - 零个或多个
    • 加号 - 一个或多个

正则表达式可能看起来很奇怪,因为它太简洁了

学习它的最佳(唯一?)方法是通过练习。否则,您会觉得自己只是在阅读规则列表。
让我们花 15 分钟开始学习 regexone 课程。

regexone课程

第 1 课:简介和 ABC

正则表达式在从文本(例如代码、日志文件、电子表格甚至文档)中提取信息时非常有用。虽然形式语言背后有很多理论,但以下课程和示例将探索正则表达式的更实际用途,以便您尽快使用它们。

使用正则表达式时要认识到的第一件事是,一切本质上都是字符,我们正在编写模式来匹配特定的字符序列(也称为字符串)。大多数模式使用普通 ASCII,其中包括字母、数字、标点符号和键盘上的其他符号,如 %#$@!,但 unicode 字符也可用于匹配任何类型的国际文本。

下面是几行文本,请注意当您在下面的输入字段中键入时,文本如何更改以突出显示每行上的匹配字符。要继续下一课,您需要使用每节课中介绍的新语法和概念来编写与所有提供的行匹配的模式。

继续尝试编写一个与所有三行匹配的模式,它可能就像每行上的常用字母一样简单。
在这里插入图片描述

第 1½ 课:123s

字符包括普通字母,也包括数字。事实上,数字 0-9 也只是字符,如果你看 ASCII 表,它们会按顺序列出。
在各个课程中,你将了解正则表达式中使用的许多特殊元字符,这些元字符可用于匹配特定类型的字符。在这种情况下,字符 \d 可以代替 0 到 9 之间的任何数字。前面的斜线将其与简单的 d 字符区分开来,并表示它是一个元字符。
下面是包含数字的几行文本。尝试编写一个与下面字符串中的所有数字匹配的模式,并注意你的模式如何匹配字符串中的任何位置,而不仅仅是从第一个字符开始。我们将在后面的课程中学习如何控制它。
在这里插入图片描述

第 2 课:点

在某些纸牌游戏中,小丑是通配符,可以代表牌组中的任意一张牌。使用正则表达式,您经常会匹配一些您不知道其确切内容的文本,除了它们共享一个共同的模式或结构(例如电话号码或邮政编码)。

同样,还有一个通配符的概念,它由 .(点)元字符表示,可以匹配任何单个字符(字母、数字、空格、所有内容)。您可能会注意到,这实际上会覆盖句点字符的匹配,因此为了专门匹配句点,您需要相应地使用斜线 . 来转义点。

下面是几个字符不同但长度相同的字符串。尝试编写一个可以匹配前三个字符串但不能匹配最后一个字符串(要跳过)的单个模式。您可能会发现您必须转义点元字符才能匹配某些行中的句点。
在这里插入图片描述

第 3 课:匹配特定字符

上一课中的点元字符非常强大,但有时也过于强大。例如,如果我们要匹配电话号码,我们不想验证字母“(abc) def-ghij”是否为有效数字!

有一种使用正则表达式匹配特定字符的方法,方法是将它们定义在方括号内。例如,模式 [abc] 只会匹配单个 a、b 或 c 字母,而不会匹配其他任何字母。

下面是几行,我们只想匹配前三个字符串,而不是后三个字符串。请注意,如果我们使用点,我们无法避免匹配后三个字符串,但必须使用上面的符号具体定义要匹配哪些字母。
在这里插入图片描述

第 4 课:排除特定字符

在某些情况下,我们可能知道有些特定字符我们不想匹配,例如,我们可能只想匹配区号不为 650 的电话号码。

为了表示这一点,我们使用一个类似的表达式,使用方括号和 ^(帽子)排除特定字符。例如,模式[^abc]将匹配除字母 a、b 或 c 之外的任何单个字符。

使用下面的字符串,尝试编写一个仅匹配活体动物(猪、狗,但不是沼泽)的模式。请注意,大多数此类模式也可以使用上一课中的技巧来编写,因为它们实际上是同一枚硬币的两面。通过两种选择,您可以决定在编写自己的模式时哪种模式更容易编写和理解。
在这里插入图片描述

第 5 课:字符范围

我们刚刚学习了如何创建匹配或排除特定字符的模式——但如果我们想要匹配一个可以位于连续字符范围内的字符怎么办?我们只能将它们全部列出吗?

幸运的是,使用方括号表示法时,可以使用短划线表示字符范围来匹配连续字符列表中的字符。例如,模式 [0-6] 仅匹配从零到六的任何单个数字字符,而不匹配其他字符。同样,[^n-p]仅匹配除字母 n 到 p 之外的任何单个字符。

还可以在同一组括号中使用多个字符范围以及单个字符。例如,字母数字 \w 元字符等同于字符范围 [A-Za-z0-9_],通常用于匹配英文文本中的字符。

在下面的练习中,请注意所有匹配和跳过行都有模式,并使用括号表示法匹配或跳过每行中的每个字符。请注意,模式区分大小写,并且 a-z 与 A-Z 在匹配的字符方面有所不同(小写与大写)。
在这里插入图片描述

第 6 课:捕捉一些 zzz

注意:下面重复语法的某些部分并不是所有正则表达式实现都支持的。

到目前为止,我们已经学会了如何指定我们想要匹配的字符范围,但是我们想要匹配的字符重复次数呢?我们可以这样做的一种方法是明确说明我们想要的字符数,例如 \d\d​​\d 可以匹配三个数字。

更方便的方法是使用花括号表示法指定我们想要的每个字符的重复次数。例如,a{3} 将匹配 a 字符三次。某些正则表达式引擎甚至允许您为这个重复指定一个范围,例如,a{1,3} 将匹配 a 字符不超过 3 次,但不少于一次。

此量词可以与任何字符或特殊元字符一起使用,例如 w{3}(三个 w)、[wxy]{5}(五个字符,每个字符可以是 w、x 或 y)和 .{2,6}(2 到 6 个任意字符)。

在下面的几行中,最后一个只有一个 z 的字符串并不是我们所认为的俚语“wazzup?”的正确拼写。尝试使用上面的花括号符号编写一个仅匹配前两个拼写的模式。
在这里插入图片描述

第 7 课:Kleene 先生,Kleene 先生

正则表达式中一个强大的概念是能够匹配任意数量的字符。例如,假设您编写了一个表单,其中有一个捐赠字段,该字段接受以美元为单位的数值。一个富有的用户可能会顺便过来并想捐赠 25,000 美元,而普通用户可能想捐赠 25 美元。

表达这种模式的一种方法是使用所谓的 Kleene Star 和 Kleene Plus,它们本质上表示它后面的 0 个或更多字符或 1 个或更多字符(它总是跟在一个字符或组后面)。例如,为了匹配上面的捐赠,我们可以使用模式 \d* 来匹配任意数量的数字,但更严格的正则表达式是 \d+,它确保输入字符串至少有一个数字。

这些量词可以与任何字符或特殊元字符一起使用,例如 a+(一个或多个 a)、[abc]+(一个或多个 a、b 或 c 字符)和 .*(零个或多个任意字符)。

以下是一些可以使用星号和加号元字符进行匹配的简单字符串。
在这里插入图片描述

第 8 课:可选字符

正如您在上一课中看到的,Kleene 星号和加号允许我们匹配一行中的重复字符。

匹配和提取文本时非常常见的另一个量词是 ?(问号)元字符,它表示可选性。此元字符允许您匹配前面的字符或组中的任何一个或零个。例如,模式 ab?c 将匹配字符串“abc”或“ac”,因为 b 被视为可选的。

与点元字符类似,问号是一个特殊字符,您必须使用斜线 ? 对其进行转义才能匹配字符串中的普通问号字符。

在下面的字符串中,请注意单词“file”的复数如何取决于找到的文件数量。尝试编写一个使用可选性元字符的模式,以仅匹配找到一个或多个文件的行。
在这里插入图片描述

第 9 课:所有这些空格

处理现实世界的输入(例如日志文件甚至用户输入)时,很难不遇到空格。我们使用它来格式化信息片段,使其更易于阅读和视觉扫描,而单个空格可能会破坏最简单的正则表达式。

您将在正则表达式中使用的最常见空格形式是空格 (␣)、制表符 (\t)、换行符 (\n) 和回车符 (\r)(在 Windows 环境中很有用),这些特殊字符与它们各自的每个空格匹配。此外,空格特殊字符 \s 将匹配上述任何特定空格,在处理原始输入文本时非常有用。

在下面的字符串中,您会发现每行的内容都从行的索引处缩进了一些空格(数字是文本的一部分)。尝试编写一个模式,可以匹配在数字和内容之间包含空格字符的每一行。请注意,空格字符与任何其他字符一样,并且星号和加号等特殊元字符也可以使用。
在这里插入图片描述

第 10 课:开始和结束

到目前为止,我们一直在编写正则表达式来部分匹配所有文本中的部分内容。有时这并不可取,例如,我们想在日志文件中匹配单词“success”。我们当然不希望该模式匹配一​​行“Error: unsuccessful operation”!这就是为什么编写尽可能具体的正则表达式通常是最佳做法,以确保在与真实文本匹配时不会出现误报。

收紧模式的一种方法是使用特殊的 ^(帽子)和 $(美元符号)元字符定义一个描述行的开始和结束的模式。在上面的例子中,我们可以使用模式 ^success 仅匹配以单词“success”开头的行,但不匹配行“Error: unsuccessful operation”。如果将帽子和美元符号结合起来,则可以创建一个从开头和结尾完全匹配整行的模式。

请注意,这与括号 [^...]内用于排除字符的帽子不同,后者在阅读正则表达式时可能会造成混淆。

尝试使用这些新的特殊字符匹配下面的每个字符串。
在这里插入图片描述

第 11 课:匹配组

正则表达式不仅允许我们匹配文本,还允许我们提取信息以供进一步处理。这是通过定义字符组并使用特殊括号 ( 和 ) 元字符捕获它们来实现的。一对括号内的任何子模式都将作为一个组被捕获。在实践中,这可用于从各种数据中提取电话号码或电子邮件等信息。

例如,假设您有一个命令行工具来列出云中的所有图像文件。然后,您可以使用诸如 ^(IMG\d+\.png)$ 之类的模式来捕获和提取完整文件名,但如果您只想捕获不带扩展名的文件名,则可以使用仅捕获句点之前部分的模式 ^(IMG\d+)\.png$

继续尝试使用它来编写一个仅匹配以下 PDF 文件的文件名(不包括扩展名)的正则表达式。
在这里插入图片描述

第 12 课:嵌套组

处理复杂数据时,您很容易发现自己必须提取多层信息,这可能导致嵌套组。通常,捕获组的结果按其定义顺序排列(按左括号顺序排列)。

以上一课中的示例为例,捕获列表中所有图像文件的文件名。如果每个图像文件的文件名中都有一个连续的图片编号,则可以使用相同的模式提取文件名和图片编号,方法是编写一个表达式,如 ^(IMG(\d+))\.png$(使用嵌套括号捕获数字)。

嵌套组在模式中从左到右读取,第一个捕获组是第一个括号组的内容,等等。

对于以下字符串,编写一个表达式,匹配并捕获完整日期以及日期的年份。
在这里插入图片描述

第 13 课:更多小组作业

正如您在前面的课程中看到的,所有量词,包括星号 *、加号 +、重复 {m,n} 和问号 ?,都可以在捕获组模式中使用。这是将量词应用于字符序列而不是单个字符本身的唯一方法。

例如,如果我知道电话号码可能包含或不包含区号,则正确的模式将测试整个数字组 (\d{3})? 的存在,而不是单个字符本身(这将是错误的)。

根据您使用的正则表达式引擎,您还可以使用非捕获组,这将允许您匹配组但不让它显示在结果中。

以下是几种不同的常见显示分辨率,请尝试捕获每个显示器的宽度和高度。
在这里插入图片描述

第 14 课:一切都是有条件的

正如我们之前提到的,精确总是好的,这适用于编码、交谈甚至正则表达式。例如,您不会为某人写一份购物清单来购买更多。*,因为您不知道会得到什么。相反,您会写购买更多牛奶或购买更多面包,而在正则表达式中,我们实际上可以明确定义这些条件。

具体来说,在使用组时,您可以使用 |(逻辑或,又称管道)来表示不同的可能字符集。在上面的例子中,我可以编写模式“Buy more (milk|bread|juice)”来仅匹配字符串购买更多牛奶、购买更多面包或购买更多果汁。

与普通组一样,您可以在条件中使用任何字符或元字符序列,例如,([cb]ats*|[dh]ogs?) 将匹配猫或蝙蝠,或者狗或猪。编写包含许多条件的模式可能难以阅读,因此如果它们太复杂,您应该考虑将它们分成单独的模式。

继续尝试编写一个条件模式,该模式仅匹配下面带有小毛茸茸生物的行。
在这里插入图片描述

第 15 课:其他特殊字符

本课将介绍一些额外的元字符以及捕获组的结果。

我们已经学习了最常见的元字符,即使用 \d 捕获数字、使用 \s 捕获空格以及使用 \w 捕获字母数字字母和数字,但正则表达式还提供了一种使用大写字母指定每个元字符的对立集的方法。例如,\D 表示任何非数字字符,\S 表示任何非空格字符,\W 表示任何非字母数字字符(如标点符号)。根据您编写正则表达式的方式,使用其中一个或另一个可能会更容易。

此外,还有一个特殊的元字符 \b,它匹配单词和非单词字符之间的边界。它在捕获整个单词时最有用(例如,通过使用模式 \w+\b)。

我们不会在这些课程中详细探讨的一个概念是反向引用,主要是因为它因实现而异。但是,许多系统允许您使用 \0(通常是完整匹配的文本)、\1(组 1)、\2(组 2)等来引用捕获的组。这很有用,例如,当您在文本编辑器中使用正则表达式进行搜索和替换以交换两个数字时,您可以搜索“(\d+)-(\d+)”并将其替换为“\2-\1”,以将第二个捕获的数字放在第一位,将第一个捕获的数字放在第二位。

下面是一些不同的字符串,尝试不同类型的元字符或我们在前面的课程中学到的任何内容,并在您准备好时继续。
在这里插入图片描述

第X课:超越无限!

恭喜您完成课程!我们希望这些课程能让您更多地了解正则表达式以及如何在日常使用中应用它们。
正则表达式中仍有一些主题我们尚未探索,例如贪婪表达式与非贪婪表达式、posix 表示法等等。我们将尝试在以后的课程中进一步阐述这些主题。
现在,继续练习问题,学习如何将正则表达式用于实际用途。

问题 1:匹配十进制数

乍一看,编写正则表达式来匹配数字应该很容易,对吧?

我们有 \d 特殊字符来匹配任何数字,我们需要做的就是匹配小数点,对吧?对于简单的数字,这可能是正确的,但在处理科学或财务数字时,您经常需要处理正数和负数、有效数字、指数,甚至不同的表示形式(例如用于分隔千和百万的逗号)。

以下是您可能会遇到的几种不同格式的数字。请注意,您必须使用点元字符匹配小数点本身,而不是任意字符。如果您在跳过最后一个数字时遇到困难,请注意该数字与其余数字相比如何结束行。
在这里插入图片描述

问题 2:匹配电话号码

根据您获得的输入类型,验证电话号码是另一项棘手的任务。州外的电话号码需要区号,国际号码需要前缀,这会增加正则表达式的复杂性,人们输入电话号码的个人偏好也会增加复杂性(例如,有些人输入破折号或空格,而其他人则不输入)。

以下是您在使用真实数据时可能会遇到的一些电话号码,编写一个与号码匹配并捕获正确区号的正则表达式。
在这里插入图片描述

问题 3:匹配电子邮件

处理 HTML 表单时,使用正则表达式验证表单输入通常很有用。特别是,由于规范的复杂性,电子邮件很难正确匹配,我建议使用内置语言或框架函数,而不是自己动手。但是,您可以使用我们迄今为止学到的知识构建一个非常强大的正则表达式,该表达式可以非常轻松地匹配大量常见电子邮件。

需要注意的一件事是,许多人使用一次性的加号寻址,例如“name+filter@gmail.com”,它直接到达“name@gmail.com”,但可以使用额外信息进行过滤。此外,某些域名有多个组件,例如,您可以在“hellokitty.hk.com”注册域名,并拥有一个格式为“ilove@hellokitty.hk.com”的电子邮件,因此在匹配电子邮件的域名部分时必须小心。

下面是一些常见的电子邮件,在此示例中,尝试捕获电子邮件的名称,不包括过滤器(+ 字符及之后)和域(@ 字符及之后)。
在这里插入图片描述

问题 4:匹配 HTML

如果您正在寻找一种强大的 HTML 解析方法,正则表达式通常不是答案,因为当今互联网上的 html 页面很脆弱——常见的错误,如缺少结束标记、标记不匹配、忘记关闭属性引号,都会破坏一个完美的正则表达式。相反,您可以使用 Beautiful Soup 或 html5lib(均为 Python)或 phpQuery(PHP)等库,它们不仅可以解析 HTML,还允许您快速轻松地转到 DOM。

话虽如此,您经常需要在编辑器中快速匹配标记和标记内容,如果您可以保证输入,正则表达式是一个很好的工具。正如您在下面的示例中看到的那样,您可能需要注意一些具有额外转义引号和嵌套标记的奇怪属性。

继续为以下示例编写正则表达式。
在这里插入图片描述

问题 5:匹配特定文件名

如果您经常使用 Linux 或命令行,则经常要处理文件列表。大多数文件都有文件名部分和扩展名,但在 Linux 中,隐藏文件没有文件名也很常见。

在这个简单的示例中,仅提取图像文件的文件名和扩展名类型(不包括当前正在编辑的图像的临时文件)。图像文件定义为 .jpg、.png 和 .gif。
在这里插入图片描述

问题 6:从行首和行尾修剪空格

有时,您会发现日志文件中的空格格式不正确,行缩进过多或不足。解决此问题的一种方法是使用编辑器的搜索替换和正则表达式来提取行的内容,而不包含多余的空格。

我们之前已经了解了如何分别使用帽子 ^ 和美元符号 $ 来匹配整行文本。当与空格 \s 结合使用时,您可以轻松跳过所有前面和后面的空格。

编写一个简单的正则表达式来捕获每行的内容,而不包含多余的空格。
在这里插入图片描述

问题 7:从日志文件中提取信息

在此示例中,我们将使用 Android adb 调试会话的实际输出。您的目标是使用我们迄今为止学到的任何正则表达式技术来提取堆栈跟踪的文件名、方法名称和行号(它们遵循“at package.class.methodname(filename:linenumber)”的形式)。

祝你好运!
在这里插入图片描述

问题 8:从 URL 解析和提取数据

在处理网络上的文件和资源时,您经常会遇到可以直接解析和处理的 URI 和 URL。大多数标准库都有类来解析和构造此类标识符,但如果您需要在日志或更大的文本语料库中匹配它们,则可以使用正则表达式轻松地从其结构化格式中提取信息。

URI 或统一资源标识符是资源的表示,通常由方案、主机、端口(可选)和资源路径组成,分别如下所示。

http://regexone.com:80/page
方案描述了要通信的协议,主机和端口描述了资源的来源,完整路径描述了资源在来源的位置。

在下面的练习中,尝试提取列出的所有资源的协议、主机和端口。
在这里插入图片描述

问题 X:无穷大和超越!

恭喜您解决了所有问题!要了解如何在一些常见的编程语言中使用正则表达式,请继续阅读上面标题菜单中的参考资料。否则,我们希望您能够在日常工作中开始应用正则表达式!

正则表达式的优点和缺点

正则表达式的优点是什么?

  • 简洁而强大的模式匹配 DSL
  • 受多种计算机语言支持,包括 SQL

正则表达式的缺点是什么?

  • 脆弱
  • 难以编写,正确性可能很复杂
  • 难以阅读

重新审视标记化

在之前的课程中,我们使用了 tokenizer。现在,让我们学习如何自己做这件事,并更好地理解 tokenization。
如果我们需要创建自己的 token 怎么办?

import re
re_punc = re.compile("([\"\''().,;:/_?!—\-])") # add spaces around punctuation
re_apos = re.compile(r"n ' t ")    # n't
re_bpos = re.compile(r" ' s ")     # 's
re_mult_space = re.compile(r"  *") # replace multiple spaces with just one

def simple_toks(sent):
    sent = re_punc.sub(r" \1 ", sent)
    sent = re_apos.sub(r" n't ", sent)
    sent = re_bpos.sub(r" 's ", sent)
    sent = re_mult_space.sub(' ', sent)
    return sent.lower().split()

这里re_punc匹配标点符号,re_apos匹配n't结构,re_bpos匹配's结构,re_mult_space匹配一个或多个空格,调用re_punc正则表达式对象的sub方法将匹配到的标点替换为标点前后一个空格,调用re_apos把所有匹配到的替换为n't,调用re_bpossub方法将匹配到的替换为's,然后用re_mult_spacesub方法将多个空格变成一个空格。

text = "I don't know who Kara's new friend is-- is it 'Mr. Toad'?"
' '.join(simple_toks(text))
"i do n't know who kara 's new friend is - - is it ' mr . toad ' ?"
text2 = re_punc.sub(r" \1 ", text); text2
"I don ' t know who Kara ' s new friend is -  -  is it  ' Mr .  Toad '  ? "
text3 = re_apos.sub(r" n't ", text2); text3
"I do n't know who Kara ' s new friend is -  -  is it  ' Mr .  Toad '  ? "
text4 = re_bpos.sub(r" 's ", text3); text4
"I do n't know who Kara 's new friend is -  -  is it  ' Mr .  Toad '  ? "
re_mult_space.sub(' ', text4)
"I do n't know who Kara 's new friend is - - is it ' Mr . Toad ' ? "
sentences = ['All this happened, more or less.',
             'The war parts, anyway, are pretty much true.',
             "One guy I knew really was shot for taking a teapot that wasn't his.",
             'Another guy I knew really did threaten to have his personal enemies killed by hired gunmen after the war.',
             'And so on.',
             "I've changed all their names."]
tokens = list(map(simple_toks, sentences))
tokens
[['all', 'this', 'happened', ',', 'more', 'or', 'less', '.'],
 ['the',
  'war',
  'parts',
  ',',
  'anyway',
  ',',
  'are',
  'pretty',
  'much',
  'true',
  '.'],
 ['one',
  'guy',
  'i',
  'knew',
  'really',
  'was',
  'shot',
  'for',
  'taking',
  'a',
  'teapot',
  'that',
  'was',
  "n't",
  'his',
  '.'],
 ['another',
  'guy',
  'i',
  'knew',
  'really',
  'did',
  'threaten',
  'to',
  'have',
  'his',
  'personal',
  'enemies',
  'killed',
  'by',
  'hired',
  'gunmen',
  'after',
  'the',
  'war',
  '.'],
 ['and', 'so', 'on', '.'],
 ['i', "'", 've', 'changed', 'all', 'their', 'names', '.']]

一旦我们有了 token,我们就需要将它们转换为整数 ID。我们还需要知道我们的词汇表,并找到一种在单词和 ID 之间进行转换的方法。

import collections
PAD = 0; SOS = 1

def toks2ids(sentences):
    voc_cnt = collections.Counter(t for sent in sentences for t in sent)
    vocab = sorted(voc_cnt, key=voc_cnt.get, reverse=True)
    vocab.insert(PAD, "<PAD>")
    vocab.insert(SOS, "<SOS>")
    w2id = {w:i for i,w in enumerate(vocab)}
    ids = [[w2id[t] for t in sent] for sent in sentences]
    return ids, vocab, w2id, voc_cnt
ids, vocab, w2id, voc_cnt = toks2ids(tokens)
ids
[[5, 13, 14, 3, 15, 16, 17, 2],
 [6, 7, 18, 3, 19, 3, 20, 21, 22, 23, 2],
 [24, 8, 4, 9, 10, 11, 25, 26, 27, 28, 29, 30, 11, 31, 12, 2],
 [32, 8, 4, 9, 10, 33, 34, 35, 36, 12, 37, 38, 39, 40, 41, 42, 43, 6, 7, 2],
 [44, 45, 46, 2],
 [4, 47, 48, 49, 5, 50, 51, 2]]

vocab
['<PAD>',
 '<SOS>',
 '.',
 ',',
 'i',
 'all',
 'the',
 'war',
 'guy',
 'knew',
 'really',
 'was',
 'his',
 'this',
 'happened',
 'more',
 'or',
 'less',
 'parts',
 'anyway',
 'are',
 'pretty',
 'much',
 'true',
 'one',
 'shot',
 'for',
 'taking',
 'a',
 'teapot',
 'that',
 "n't",
 'another',
 'did',
 'threaten',
 'to',
 'have',
 'personal',
 'enemies',
 'killed',
 'by',
 'hired',
 'gunmen',
 'after',
 'and',
 'so',
 'on',
 "'",
 've',
 'changed',
 'their',
 'names']

上面的 vocab 变量的另一个名称是什么?

w2id
{'<PAD>': 0,
 '<SOS>': 1,
 '.': 2,
 ',': 3,
 'i': 4,
 'all': 5,
 'the': 6,
 'war': 7,
 'guy': 8,
 'knew': 9,
 'really': 10,
 'was': 11,
 'his': 12,
 'this': 13,
 'happened': 14,
 'more': 15,
 'or': 16,
 'less': 17,
 'parts': 18,
 'anyway': 19,
 'are': 20,
 'pretty': 21,
 'much': 22,
 'true': 23,
 'one': 24,
 'shot': 25,
 'for': 26,
 'taking': 27,
 'a': 28,
 'teapot': 29,
 'that': 30,
 "n't": 31,
 'another': 32,
 'did': 33,
 'threaten': 34,
 'to': 35,
 'have': 36,
 'personal': 37,
 'enemies': 38,
 'killed': 39,
 'by': 40,
 'hired': 41,
 'gunmen': 42,
 'after': 43,
 'and': 44,
 'so': 45,
 'on': 46,
 "'": 47,
 've': 48,
 'changed': 49,
 'their': 50,
 'names': 51}

正则表达式有什么用途?

  • 查找/搜索
  • 查找和替换
  • 清理

不要忘记 Python 的字符串方法

str.find?

正则表达式 vs. 字符串方法

  • 字符串方法更容易理解。
  • 字符串方法更清楚地表达意图。
  • 正则表达式处理更广泛的用例。
  • 正则表达式可以独立于语言。
  • 正则表达式可以更快地进行扩展。

那么unicode怎么样?

message = "😒🎦 🤢🍕"

re_frown = re.compile(r"😒|🤢")
re_frown.sub(r"😊", message)
'😊🎦 😊🍕'

正则表达式错误:

  • False positives(类型 I):匹配了我们不应该匹配的字符串

  • False negatives(类型 II):不匹配我们本应匹配的字符串

降低任务的错误率通常需要两种相互对立的努力:

  1. 尽量减少假阳性
  2. 尽量减少假阴性
    对两者进行测试很重要!

在理想情况下,您可以尽量减少两者,但在现实中,您经常需要用其中一种来换取另一种。

总结

  1. 我们使用正则表达式作为元语言来查找文本块中的字符串模式
  2. r"" 是 Python 正则表达式的 IRL 朋友
  3. 我们只是进行二元分类,因此使用相同的性能指标
  4. 你会在正则表达式中犯很多错误😩。
  • 假阳性:以为自己是对的,但其实你是错的
  • 假阴性:遗漏了一些东西

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/699546.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

记录项目打包时候找不到本地仓库的依赖的解决方法

进入本地仓库对应jar的目录 删除_remote_reposotories文件即可

Photoshop界面介绍

Adobe Photoshop 2024版&#xff08;通称“Photoshop 2024”或简写为“PS 2024”&#xff09;下载方式【点我获取下载链接】 百度网盘下载https://pan.baidu.com/s/1JmuK8RMHt2Yyb7NFtgO2uQ?pwdSIMS Photoshop界面介绍 Photoshop&#xff0c;简称PS&#xff0c;是Adobe …

【MySQL】存储引擎

https://www.bilibili.com/video/BV1Kr4y1i7ru?p64 https://jimhackking.github.io/%E8%BF%90%E7%BB%B4/MySQL%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/#more MySQL体系结构&#xff1a; 连接层 最上层是一些客户端和链接服务&#xff0c;主要完成一些类似于连接处理、授权认证…

【代码随想录】【算法训练营】【第35天】 [1005]K次取反后最大化的数组和 [134]加油站 [135]分发糖果

前言 思路及算法思维&#xff0c;指路 代码随想录。 题目来自 LeetCode。 day 35&#xff0c;连休两天~ 题目详情 [1005] K次取反后最大化的数组和 题目描述 1005 K次取反后最大化的数组和 解题思路 前提&#xff1a;数组 思路&#xff1a;优先负数取反&#xff0c;未…

利用AI机器学习,助力发动机舱电磁场强仿真,轻松实现快速预测

当下工业仿真面临的难题&#xff1f; 在使用 Altair Feko 进行空间场强计算时&#xff0c;每次查询新坐标点的场强幅值都需要重新进行计算&#xff0c;这不仅耗时&#xff08;约20-30分钟&#xff09;&#xff0c;而且还需要考虑高级算力的排队时间。这种效率瓶颈严重限制了快速…

springboot三层架构与MVC,以及三层架构入门

三层架构与MVC 1. 三层架构是什么 把各个功能模块划分为表示层&#xff0c;业务逻辑层&#xff0c;和数据访问层三层架构&#xff0c;各层之间采用接口相互访问&#xff0c;并通过对象模型的实体类&#xff08;model&#xff09;作为数据传递的载体&#xff0c;不同的对象模型…

Rust : windows下protobuf和压缩传输方案

此前dbpystream库是用python开发 web api。今天在rust中试用一下protobuf。 本文关键词&#xff1a;编译器、protobuf、proto文件、序列化、zstd压缩&#xff0c;build。 一、 protobuf编译器下载 具体见相关文章。没有编译器&#xff0c;protobuf无法运行。 windows参见&am…

鸿蒙原生开发——轻内核A核源码分析系列三 物理内存(2)

3.1.2.3 函数OsVmPhysLargeAlloc 当执行到这个函数时&#xff0c;说明空闲链表上的单个内存页节点的大小已经不能满足要求&#xff0c;超过了第9个链表上的内存页节点的大小了。⑴处计算需要申请的内存大小。⑵从最大的链表上进行遍历每一个内存页节点。⑶根据每个内存页的开始…

02-DHCP原理与配置

1、DHCP的工作原理 当局域网中有大量的主机时&#xff0c;如果逐个为每一台主机手动设置IP地址、默认网关、DNS服务器地址等网络参数&#xff0c;这显然是一个费力也未必讨好的办法。 而DHCP服务器的应用&#xff0c;正好可以解决这一问题。 1.1 DHCP是什么 DHCP——动态主机…

[2024-06]-[大模型]-[Ollama] 0-相关命令

常用的ollama命令[持续更新中] ollama更新&#xff1a; curl https://ollama.ai/install.sh |sh带着flash attention启动&#xff1a; OLLAMA_FLASH_ATTENTION1 ollama serve停止ollama服务&#xff1a; sudo systemctl stop ollama note&#xff1a;目前遇到sudo systemctl …

驱动开发之 input 子系统

1.input 子系统介绍 input 就是输入的意思&#xff0c;input 子系统就是管理输入的子系统&#xff0c;和 pinctrl、gpio 子系统 一样&#xff0c;都是 Linux 内核针对某一类设备而创建的框架。比如按键输入、键盘、鼠标、触摸屏等 等这些都属于输入设备&#xff0c;不同的输入…

一文教你如何实现并发请求的失败自动重试及重试次数限制

需求 在并发接口请求的时候&#xff0c;能够自动对失败的请求进行重发尝试&#xff08;超过指定重试次数则不再重试&#xff09;,并将最终的结果返回&#xff08;包含每个请求是否成功、返回结果&#xff09; 核心思路 代码实现 使用案例 为了演示我们代码的最终实现效果&a…

使用 python 将 Markdown 文件转换为 ppt演示文稿

在这篇博客中&#xff0c;我们将展示如何使用 wxPython 创建一个简单的图形用户界面 (GUI)&#xff0c;以将 Markdown 文件转换为 PowerPoint 演示文稿。我们将利用 markdown2 模块将 Markdown 转换为 HTML&#xff0c;并使用 python-pptx 模块将 HTML 内容转换为 PowerPoint 幻…

HarmonyOS未来五年的市场展望

一、引言 随着科技的不断进步和消费者对于智能化设备需求的日益增长&#xff0c;操作系统作为连接硬件与软件的核心平台&#xff0c;其重要性愈发凸显。HarmonyOS&#xff08;鸿蒙系统&#xff09;&#xff0c;作为华为自主研发的分布式操作系统&#xff0c;自诞生以来便备受瞩…

6月11号作业

思维导图 #include <iostream> using namespace std; class Animal { private:string name; public:Animal(){}Animal(string name):name(name){//cout << "Animal&#xff1b;有参" << endl;}virtual void perform(){cout << "讲解员的…

UE4_后期_ben_模糊和锐化滤镜

学习笔记&#xff0c;不喜勿喷&#xff0c;侵权立删&#xff0c;祝愿生活越来越好&#xff01; 本篇教程主要介绍后期处理的简单模糊和锐化滤镜效果&#xff0c;学习之前首先要回顾下上节课介绍的屏幕扭曲效果&#xff1a; 这是全屏效果&#xff0c;然后又介绍了几种蒙版&#…

【PX4-AutoPilot教程-TIPS】PX4加速度计陀螺仪滤波器参数设置

PX4加速度计陀螺仪滤波器参数设置 前期准备滤波前FFT图滤波后FFT图 环境&#xff1a; 日志分析软件 : Flight Review PX4 &#xff1a;1.13.0 前期准备 进行滤波器参数设置的前提是飞机简单调试过PID已经可以稳定起飞&#xff0c;开源飞控的很多默认参数是可以让飞机平稳起…

springSecurity学习笔记(一)

简介 Spring Security是一个Java框架&#xff0c;用于保护应用程序的安全性。它提供了一套全面的安全解决方案&#xff0c;包括身份验证、授权、防止攻击等功能。Spring Security基于过滤器链的概念&#xff0c;可以轻松地集成到任何基于Spring的应用程序中。它支持多种身份验…

记一次华为2288H V5更换主板的辛酸

1、开机提示找不到设备&#xff0c;通过带外检查硬盘raid是否正常&#xff0c;如果正常就不是硬件问题&#xff0c;也不会是线没接好 2、网络不通&#xff0c;服务重启啥的都正常不会报错&#xff0c;就是ping不通网关&#xff0c;后来通过带外发现是网卡漂移了。 核对mac地址发…

Docker 国内镜像源更换

实现 替换docker 镜像源 前提要求 安装 docker docker-compose 参考创建一键更换docker国内镜像源 Docker 镜像代理DaoCloud 镜像站百度云 https://mirror.baidubce.com南京大学镜像站