PYTHON-使用正则表达式进行模式匹配

目录

    • Python 正则表达式
      • Finding Patterns of Text Without Regular Expressions
      • Finding Patterns of Text with Regular Expressions
      • Creating Regex Objects
      • Matching Regex Objects
      • Review of Regular Expression Matching
      • More Pattern Matching with Regular Expressions
      • Grouping with Parentheses
      • Matching Multiple Groups with the Pipe
      • Optional Matching with the Question Mark
      • Matching Zero or More with the Star
      • Matching One or More with the Plus
      • Matching Specific Repetitions with Braces
      • Greedy and Non-greedy Matching
      • The findall() Method
      • Character Classes
      • Making Your Own Character Classes
      • The Caret and Dollar Sign Characters
      • The Wildcard Character
      • Matching Everything with Dot-Star
      • Matching Newlines with the Dot Character
      • Review of Regex Symbols
      • Case-Insensitive Matching
      • Substituting Strings with the sub() Method
      • Managing Complex Regexes
      • Combining re.IGNORECASE, re.DOTALL, and re.VERBOSE
      • Project: Phone Number and Email Address Extractor
        • Step 1: Create a Regex for Phone Numbers
        • Step 2: Create a Regex for Email Addresses
        • Step 3: Find All Matches in the Clipboard Text
        • Step 4: Join the Matches into a String for the Clipboard

Python 正则表达式

在这里插入图片描述

您可能熟悉通过按 CTRL-F 并输入您要查找的单词来搜索文本。正则表达式更进一步:它们允许您指定要搜索的文本模式。您可能不知道企业的确切电话号码,但如果您居住在美国或加拿大,您知道它将是三位数字,后跟连字符,然后是四位数字(以及可选的三位数区号,位于开始)。作为人类,您看到电话号码时就是这样知道的:415-555-1234 是电话号码,但 4,155,551,234 不是。
我们每天还识别各种其他文本模式:电子邮件地址中间有@符号,美国社会安全号码有九个数字和两个连字符,网站URL通常有句号和正斜杠,新闻标题使用标题大小写,社交媒体主题标签以 # 开头且不包含空格等。
正则表达式很有用,但很少有非程序员了解它们,尽管大多数现代文本编辑器和文字处理程序(例如 Microsoft Word 或 OpenOffice)都具有可以基于正则表达式进行搜索的查找和查找和替换功能。正则表达式不仅对于软件用户而且对于程序员来说都可以节省大量时间。事实上,科技作家科里·多克托罗 (Cory Doctorow) 认为,我们甚至应该在编程之前就学习正则表达式:

知道[正则表达式]意味着用 3 步解决问题和用 3,000 步解决问题之间的区别。当你是一个书呆子时,你会忘记,你通过几次按键就能解决的问题可能需要其他人花费数天的乏味且容易出错的工作才能完成。

在本章中,您将首先编写一个程序来查找文本模式而不使用正则表达式,然后了解如何使用正则表达式来使代码不那么臃肿。我将向您展示与正则表达式的基本匹配,然后继续介绍一些更强大的功能,例如字符串替换和创建您自己的字符类。最后,在本章末尾,您将编写一个程序,可以自动从文本块中提取电话号码和电子邮件地址。

Finding Patterns of Text Without Regular Expressions

假设您想在字符串中查找美国电话号码。如果您是美国人,您就知道这种模式:三个数字、一个连字符、三个数字、一个连字符和四个数字。示例如下:415-555-4242。
让我们使用名为 isPhoneNumber() 的函数来检查字符串是否与此模式匹配,返回 True 或 False。打开一个新的文件编辑器选项卡并输入以下代码;然后将文件另存为 isPhoneNumber.py:

def isPhoneNumber(text):if len(text) != 12:return Falsefor i in range(0, 3):if not text[i].isdecimal():return Falseif text[3] != '-':return Falsefor i in range(4, 7):if not text[i].isdecimal():return Falseif text[7] != '-':return Falsefor i in range(8, 12):if not text[i].isdecimal():return Falsereturn True
print('Is 415-555-4242 a phone number?')
print(isPhoneNumber('415-555-4242'))
print('Is Moshi moshi a phone number?')
print(isPhoneNumber('Moshi moshi'))

当这个程序运行时,输出如下所示:
在这里插入图片描述
isPhoneNumber() 函数的代码会执行多次检查以查看文本中的字符串是否为有效的电话号码。如果其中任何检查失败,该函数将返回 False。首先,代码检查字符串是否正好是 12 个字符 ➊。然后它检查区号(即文本中的前三个字符)是否仅由数字字符 ➋ 组成。该函数的其余部分检查字符串是否遵循电话号码的模式:该号码必须在区号 ➌ 之后包含第一个连字符,再添加三个数字字符 ➍,然后再添加一个连字符 ➎,最后再添加四个数字 ➏。如果程序执行成功通过了所有检查,则返回 True ➐。

使用参数“415-555-4242”调用 isPhoneNumber() 将返回 True。使用 ‘Moshi moshi’ 调用 isPhoneNumber() 将返回 False;第一个测试失败,因为“Moshi moshi”长度不足 12 个字符。
如果您想在较大的字符串中查找电话号码,则必须添加更多代码来查找电话号码模式。将 isPhoneNumber.py 中的最后四个 print() 函数调用替换为以下内容:

message = 'Call me at 415-555-1011 tomorrow. 415-555-9999 is my office.'
for i in range(len(message)):➊ chunk = message[i:i+12]if isPhoneNumber(chunk):print('Phone number found: ' + chunk)
print('Done')

当这个程序运行时,输出将如下所示:

在这里插入图片描述for 循环的每次迭代中,消息中的 12 个字符的新块被分配给变量块 ➊。例如,在第一次迭代中,i 为 0,块被分配为 message[0:12](即字符串“Call me at 4”)。在下一次迭代中,i 为 1,块被分配为 message[1:13](字符串“all me at 41”)。换句话说,在 for 循环的每次迭代中, chunk 都采用以下值:
在这里插入图片描述
您将块传递给 isPhoneNumber() 以查看它是否与电话号码模式 ➋ 匹配,如果是,则打印该块。
继续循环message,最终chunk中的12个字符将是一个电话号码。该循环遍历整个字符串,测试每个 12 个字符的片段并打印它发现的满足 isPhoneNumber() 的任何块。一旦我们浏览完消息,我们就会打印 Done
虽然在此示例中消息中的字符串很短,但它可能有数百万个字符长,并且程序仍将在不到一秒的时间内运行。使用正则表达式查找电话号码的类似程序也将在不到一秒的时间内运行,但正则表达式可以更快地编写这些程序。

Finding Patterns of Text with Regular Expressions

以前的电话号码查找程序可以工作,但它使用大量代码来完成一些有限的事情: isPhoneNumber() 函数有 17 行,但只能查找一种模式的电话号码。电话号码格式如 415.555.4242(415) 555-4242 怎么样?如果电话号码有分机号(例如 415-555-4242 x99)怎么办? isPhoneNumber() 函数将无法验证它们。您可以为这些附加模式添加更多代码,但有一种更简单的方法。
正则表达式,简称正则表达式,是对文本模式的描述。例如,正则表达式中的 \d 代表数字字符,即从 0 到 9 的任何单个数字。正则表达式 \d\d​​\d-\d\d\d-\d\d\d\d Python 使用 isPhoneNumber() 函数来匹配与之前的 isPhoneNumber() 函数相同的文本模式:由三个数字、一个连字符、另外三个数字、另一个连字符和四个数字组成的字符串。任何其他字符串都不会与 \d\d​​\d-\d\d\d-\d\d\d\d 正则表达式匹配。
但正则表达式可以更加复杂。例如,在模式后添加大括号 ({3}) 中的 3 就像在说“匹配该模式三次”。因此,稍短的正则表达式 \d{3}-\d{3}-\d{4} 也匹配正确的电话号码格式。

Creating Regex Objects

Python 中的所有正则表达式函数都位于 re 模块中。在交互式 shell 中输入以下内容以导入此模块:
在这里插入图片描述
Note
本章中的大多数示例都需要 re 模块,因此请记住在您编写的任何脚本的开头或每次重新启动 Mu 时导入它。否则,您将收到 NameError: name 're' is not Defined 错误消息。
将表示正则表达式的字符串值传递给 re.compile() 将返回一个 Regex 模式对象(或简称为 Regex 对象)。
要创建与电话号码模式匹配的 Regex 对象,请在交互式 shell 中输入以下内容。 (请记住, \d 表示“数字字符”,而 \d\d​​\d-\d\d\d-\d\d\d\d 是电话号码模式的正则表达式。)
>>>phoneNumRegex = re.compile(r’\d\d\d-\d\d\d-\d\d\d\d’)

现在,phoneNumRegex 变量包含一个 Regex 对象。

Matching Regex Objects

Regex 对象的 search() 方法搜索它传递的字符串以查找与正则表达式的任何匹配项。如果在字符串中找不到正则表达式模式,则 search() 方法将返回 None。如果找到模式,search() 方法将返回一个 Match 对象,该对象有一个 group() 方法,该方法将从搜索字符串中返回实际匹配的文本。 (我将很快解释组。)例如,在交互式 shell 中输入以下内容:
在这里插入图片描述
mo 变量名称只是用于 Match 对象的通用名称。这个示例乍一看可能很复杂,但它比之前的 isPhoneNumber.py 程序要短得多,并且执行相同的操作。
在这里,我们将所需的模式传递给 re.compile() 并将生成的 Regex 对象存储在 phoneNumRegex 中。然后我们在 phoneNumRegex 上调用search() 并将我们想要在搜索过程中匹配的字符串传递给 search()。搜索结果存储在变量 mo 中。在此示例中,我们知道将在字符串中找到我们的模式,因此我们知道将返回一个 Match 对象。知道 mo 包含 Match 对象而不是空值 None,我们可以在 mo 上调用 group() 以返回匹配项。在 print() 函数调用中写入 mo.group() 会显示整个匹配项,415-555-4242

Review of Regular Expression Matching

虽然在 Python 中使用正则表达式有几个步骤,但每个步骤都相当简单。

  1. 使用 import re 导入正则表达式模块。
  2. 使用 re.compile() 函数创建 Regex 对象。 (记住使用原始字符串。)
  3. 将要搜索的字符串传递到 Regex 对象的 search() 方法中。这将返回一个 Match 对象。
  4. 调用 Match 对象的 group() 方法返回实际匹配文本的字符串。
    Note
    虽然我鼓励您将示例代码输入交互式 shell,但您还应该使用基于 Web 的正则表达式测试器,它可以准确地向您展示正则表达式如何与您输入的一段文本匹配。我推荐 https://pythex.org/ 上的测试器。

More Pattern Matching with Regular Expressions

既然您已经了解了使用 Python 创建和查找正则表达式对象的基本步骤,您就可以尝试它们的一些更强大的模式匹配功能了。

Grouping with Parentheses

假设您要将区号与电话号码的其余部分分开。添加括号将在正则表达式中创建组:(\d\d\d)-(\d\d\d-\d\d\d\d)。然后,您可以使用 group() 匹配对象方法从一组中获取匹配文本。
正则表达式字符串中的第一组括号将是组 1。第二组括号将是组 2。通过将整数 1 或 2 传递给 group() 匹配对象方法,您可以抓取匹配文本的不同部分。向 group() 方法传递 0 或不传递任何内容将返回整个匹配的文本。在交互式 shell 中输入以下内容:
在这里插入图片描述
如果您想一次检索所有组,请使用 groups() 方法 - 请注意名称的复数形式。
在这里插入图片描述
由于 mo.groups() 返回多个值的元组,因此您可以使用多重赋值技巧将每个值分配给单独的变量,如前面的 areaCode, mainNumber = mo.groups() 行中所示。
括号在正则表达式中具有特殊含义,但是如果需要匹配文本中的括号该怎么办?例如,您尝试匹配的电话号码可能在括号中设置了区号。在这种情况下,您需要使用反斜杠转义 ( 和 ) 字符。在交互式 shell 中输入以下内容:
在这里插入图片描述
传递给 re.compile() 的原始字符串中的 \(\) 转义字符将与实际的括号字符匹配。在正则表达式中,以下字符具有特殊含义:

. ^ $ * + ? { } [ ] \ | ( )
. ^ $ * + ? { } [ ] \ | ( )

如果您想将这些字符检测为文本模式的一部分,则需要使用反斜杠对它们进行转义:
确保仔细检查您没有将转义括号 ( 和 ) 误认为是正则表达式中的括号 ( 和 )。如果您收到有关“缺少 )”或“不平衡括号”的错误消息,则您可能忘记包含组的未转义右括号,如下例所示:
在这里插入图片描述
该错误消息告诉您,r'(\(Parentheses\)' 字符串的索引 0 处有一个左括号,缺少相应的右括号。

Matching Multiple Groups with the Pipe

||字符称为管道。您可以在任何想要匹配多个表达式之一的地方使用它。例如,正则表达式 r'Batman|Tina Fey' 将匹配“Batman”“Tina Fey”
BatmanTina Fey 同时出现在搜索字符串中时,第一次出现的匹配文本将作为 Match 对象返回。在交互式 shell 中输入以下内容:

在这里插入图片描述
您还可以使用管道来匹配多种模式之一作为正则表达式的一部分。例如,假设您想要匹配任何字符串“Batman”、“Batmobile”、“Batcopter”和“Batbat”。由于所有这些字符串都以 Bat 开头,因此如果您只能指定该前缀一次,那就太好了。这可以通过括号来完成。在交互式 shell 中输入以下内容:
在这里插入图片描述
方法调用 mo.group() 返回完整匹配的文本“Batmobile”,而 mo.group(1) 仅返回第一个括号组“mobile”内匹配文本的部分。通过使用管道字符和分组括号,您可以指定您希望正则表达式匹配的几种替代模式。
如果需要匹配实际的管道字符,请使用反斜杠对其进行转义,例如 \|

Optional Matching with the Question Mark

有时,您只想选择性地匹配某个模式。也就是说,无论该文本是否存在,正则表达式都应该找到匹配项。 字符将其前面的组标记为模式的可选部分。例如,在交互式 shell 中输入以下内容:
在这里插入图片描述
(wo)? 正则表达式的一部分表示模式 wo 是可选组。正则表达式将匹配其中包含零个实例或一个 wo 实例的文本。这就是正则表达式同时匹配“Batwoman”“Batman”的原因。
使用前面的电话号码示例,您可以使正则表达式查找包含或不包含区号的电话号码。在交互式 shell 中输入以下内容:
在这里插入图片描述
你能想到的吗意思是“匹配此问号之前的组中的零个或一个。”
如果需要匹配实际的问号字符,请使用\?进行转义。

Matching Zero or More with the Star

*(称为星号或星号)表示“匹配零个或多个”——星号之前的组可以在文本中出现任意多次。它可以完全不存在或一遍又一遍地重复。让我们再看一下蝙蝠侠的例子。
在这里插入图片描述
对于“Batman”,正则表达式的(wo)*部分与字符串中 wo 的零个实例匹配;对于“Batwoman”(wo)* 匹配 wo 的一个实例;对于“Batwowowowoman”(wo)* 匹配wo的四个实例。
如果需要匹配实际的星号字符,请在正则表达式中的星号前面加上反斜杠 \*

Matching One or More with the Plus

* 表示“匹配零个或多个”,+(或加号)表示“匹配一个或多个”。与星号不同,星号不要求其组出现在匹配的字符串中,加号前面的组必须至少出现一次。它不是可选的。在交互式shell中输入以下内容,并将其与上一节中的星号正则表达式进行比较:
在这里插入图片描述
正则表达式 Bat(wo)+man 不会匹配字符串“The Adventures of Batman”,因为加号至少需要一个 wo
如果需要匹配实际的加号字符,请在加号前面加上反斜杠以将其转义:\+。]

Matching Specific Repetitions with Braces

如果您想要重复某个组特定次数,请在正则表达式中的该组后面加上大括号中的数字。例如,正则表达式 (Ha){3} 将匹配字符串“HaHaHa”,但不会匹配“HaHa”,因为后者只有两次(Ha)组重复。
您可以通过在大括号之间写入最小值、逗号和最大值来指定范围,而不是一个数字。例如,正则表达式 (Ha){3,5} 将匹配“HaHaHa”“HaHaHaHa”“HaHaHaHaHa”
您还可以省略大括号中的第一个或第二个数字,以使最小值或最大值不受限制。例如,(Ha){3,} 将匹配 (Ha) 组的三个或多个实例,而 (Ha){,5} 将匹配零到五个实例。大括号可以帮助缩短正则表达式。这两个正则表达式匹配相同的模式:
在这里插入图片描述
这两个正则表达式也匹配相同的模式:
在这里插入图片描述
在交互式 shell 中输入以下内容:
在这里插入图片描述
此处,(Ha){3} 匹配“HaHaHa”,但不匹配“Ha”。由于它与“Ha”不匹配,search() 返回 None

Greedy and Non-greedy Matching

由于 (Ha){3,5} 可以匹配字符串 'HaHaHaHaHa' 中的三个、四个或五个Ha实例,因此您可能想知道为什么上一个大括号示例中Match对象对 group() 的调用返回'HaHaHaHaHa'而不是更短的可能性。毕竟,“HaHaHa”“HaHaHaHa”也是正则表达式(Ha){3,5}的有效匹配。
Python 的正则表达式默认是贪婪的,这意味着在不明确的情况下它们将匹配尽可能长的字符串。大括号的非贪婪(也称为惰性)版本与可能的最短字符串匹配,右大括号后跟一个问号。
在交互式shell中输入以下内容,并注意搜索同一字符串的大括号的贪婪和非贪婪形式之间的区别:
在这里插入图片描述
请注意,问号在正则表达式中可以有两种含义:声明非贪婪匹配或标记可选组。这些含义完全无关。

The findall() Method

除了search()方法之外,Regex 对象还有 findall() 方法。search()将返回搜索字符串中第一个匹配文本的 Match 对象,而findall()方法将返回搜索字符串中每个匹配的字符串。要查看 search() 如何仅在匹配文本的第一个实例上返回 Match 对象,请在交互式 shell 中输入以下内容:
在这里插入图片描述
另一方面,只要正则表达式中没有组,findall() 就不会返回 Match 对象,而是返回字符串列表。列表中的每个字符串都是与正则表达式匹配的搜索文本的一部分。在交互式 shell 中输入以下内容:
在这里插入图片描述
如果正则表达式中有组,则 findall() 将返回元组列表。每个元组代表一个找到的匹配项,其项是正则表达式中每个组的匹配字符串。要查看 findall() 的实际效果,请在交互式shell中输入以下内容(请注意,正在编译的正则表达式现在包含括号中的组):
在这里插入图片描述
要总结 findall() 方法返回的内容,请记住以下几点:

  • 当在没有组的正则表达式上调用时,例如 \d\d​​\d-\d\d\d-\d\d\d\d,方法 findall() 返回字符串匹配列表,例如 [' 415-555-9999','212-555-0000']
  • 当调用具有组的正则表达式时,例如 (\d\d\d)-(\d\d\d)-(\d\d\d\d),方法 findall() 返回元组列表字符串(每组一个字符串),例如 [('415', '555', '9999'), ('212', '555', '0000')]

Character Classes

在前面的电话号码正则表达式示例中,您了解到 \d 可以代表任何数字。也就是说,\d 是正则表达式(0|1|2|3|4|5|6|7|8|9)的简写。这样的简写字符类有很多,如表 7-1 所示。

Shorthand character classRepresents
\d0 到 9 之间的任何数字。
\D任何非 0 到 9 数字的字符。
\w任何字母、数字或下划线字符。 (将此视为匹配“单词”字符。)
\W任何非字母、数字或下划线字符的字符。
\s任何空格、制表符或换行符。 (将此视为匹配“空格”字符。)
\S除空格、制表符或换行符之外的任何字符。

字符类非常适合缩短正则表达式。字符类[0-5]将只匹配数字0到5;这比输入 (0|1|2|3|4|5) 要短得多。请注意,虽然\d匹配数字,\w 匹配数字、字母和下划线,但不存在仅匹配字母的速记字符类。 (尽管您可以使用[a-zA-Z]字符类,如下所述。)
例如,在交互式 shell 中输入以下内容:
在这里插入图片描述
正则表达式 \d+\s\w+ 将匹配包含一个或多个数字 (\d+)、后跟一个空格字符 (\s)、后跟一个或多个字母/数字/下划线字符 (\w+) 的文本。 findall() 方法返回列表中正则表达式模式的所有匹配字符串。

Making Your Own Character Classes

有时您想要匹配一组字符,但简写字符类(\d、\w、\s 等)太宽泛。您可以使用方括号定义自己的字符类。例如,字符类[aeiouAEIOU]将匹配任何元音,包括小写和大写。在交互式 shell 中输入以下内容:
在这里插入图片描述
您还可以使用连字符包含字母或数字范围。例如,字符类[a-zA-Z0-9]将匹配所有小写字母、大写字母和数字。
请注意,方括号内的正常正则表达式符号不会被如此解释。这意味着您不需要使用前面的反斜杠转义.、*、? 或 ()字符。例如,字符类 [0-5.] 将匹配数字 0 到 5 和句点。不需要写成[0-5\.]
通过在字符类的左括号后面放置插入符号 (^),可以创建负字符类。负字符类将匹配所有不属于该字符类的字符。例如,在交互式shell中输入以下内容:
在这里插入图片描述
现在,我们不是匹配每个元音,而是匹配每个非元音的字符。

The Caret and Dollar Sign Characters

您还可以在正则表达式的开头使用插入符号 (^) 来指示匹配必须出现在搜索文本的开头。同样,您可以在正则表达式末尾放置一个美元符号 ($),以指示字符串必须以此正则表达式模式结尾。您可以一起使用 ^$ 来指示整个字符串必须与正则表达式匹配 - 也就是说,仅在字符串的某些子集上进行匹配是不够的。
例如,r'^Hello' 正则表达式字符串匹配以'Hello'开头的字符串。在交互式shell中输入以下内容:
在这里插入图片描述
r'\d$' 正则表达式字符串匹配以 0 到 9 之间的数字字符结尾的字符串。在交互式 shell 中输入以下内容:
在这里插入图片描述
r'^\d+$' 正则表达式字符串匹配以一个或多个数字字符开头和结尾的字符串。在交互式shell中输入以下内容:
在这里插入图片描述
前面的交互式 shell 示例中的最后两个search()调用演示了如果使用^ $,整个字符串必须如何与正则表达式匹配。
我总是混淆这两个符号的含义,因此我使用助记符“Carrots costdollar”来提醒自己插入符号在前,美元符号在后。

The Wildcard Character

. 正则表达式中的(或点)字符称为通配符,将匹配除换行符之外的任何字符。例如,在交互式shell中输入以下内容:
在这里插入图片描述
请记住,点字符仅匹配一个字符,这就是为什么上一示例中的文本flat匹配仅匹配lat的原因。要匹配实际的点,请使用反斜杠转义点:\..

Matching Everything with Dot-Star

有时您会想要匹配所有内容。例如,假设您想要匹配字符串“First Name:”,后跟任何和所有文本,然后是“Last Name:”,最后再跟任何内容。您可以使用点星号 (.*) 来代表“任何内容”。请记住,点字符表示“除换行符之外的任何单个字符”,星号字符表示“零个或多个前面的字符”。
在这里插入图片描述
点星使用贪婪模式:它将始终尝试匹配尽可能多的文本。要以非贪婪方式匹配任何和所有文本,请使用点、星号和问号 (.*?)。与大括号一样,问号告诉Python以非贪婪的方式进行匹配。
在交互式shell中输入以下内容,查看贪婪版本和非贪婪版本之间的区别:
在这里插入图片描述
这两个正则表达式大致翻译为“匹配左尖括号,后跟任何内容,然后是右尖括号。”但是字符串 '<Toserve man> fordinner.>' 的右尖括号有两个可能的匹配项。在正则表达式的非贪婪版本中,Python 匹配最短的可能字符串:“<Toserve man>”。在贪婪版本中,Python 匹配尽可能长的字符串:“<Toserve man> fordinner.>”

Matching Newlines with the Dot Character

点星将匹配除换行符之外的所有内容。通过将 re.DOTALL 作为第二个参数传递给 re.compile(),可以使点字符匹配所有字符,包括换行符。
在这里插入图片描述
正则表达式noNewlineRegex没有将re.DOTALL传递给创建它的 re.compile() 调用,它只会匹配第一个换行符之前的所有内容,而 newlineRegex 确实将 re.DOTALL 传递给 re.compile( ),匹配一切。这就是 newlineRegex.search() 调用匹配完整字符串(包括换行符)的原因。

Review of Regex Symbols

在这里插入图片描述

Case-Insensitive Matching

通常,正则表达式将文本与您指定的确切大小写进行匹配。例如,以下正则表达式匹配完全不同的字符串:
在这里插入图片描述
但有时您只关心匹配字母,而不关心它们是大写还是小写。要使正则表达式不区分大小写,可以将 re.IGNORECASEre.I 作为第二个参数传递给 re.compile()。在交互式shell中输入以下内容:
在这里插入图片描述

Substituting Strings with the sub() Method

正则表达式不仅可以查找文本模式,还可以用新文本代替这些模式。 Regex 对象的 sub() 方法传递两个参数。第一个参数是一个字符串,用于替换任何匹配项。第二个是正则表达式的字符串。 sub() 方法返回应用了替换的字符串。
例如,在交互式 shell 中输入以下内容:
**加粗样式**
有时您可能需要使用匹配的文本本身作为替换的一部分。在 sub() 的第一个参数中,您可以键入 \1、\2、\3 等,表示“在替换中输入组 1、2、3 等的文本”。
例如,假设您想通过仅显示秘密特工姓名的第一个字母来审查他们的姓名。为此,您可以使用正则表达式代理 (\w)\w* 并将r'\1****'作为第一个参数传递给 sub()。该字符串中的\1将被第 1 组(即正则表达式的(\w)组)匹配的任何文本替换。
在这里插入图片描述

Managing Complex Regexes

如果您需要匹配的文本模式很简单,则正则表达式就可以了。但匹配复杂的文本模式可能需要长而复杂的正则表达式。您可以通过告诉 re.compile() 函数忽略正则表达式字符串内的空格和注释来缓解这种情况。这种“详细模式”可以通过将变量re.VERBOSE作为第二个参数传递给re.compile()来启用。
现在,而不是像这样难以阅读的正则表达式:
在这里插入图片描述
您可以使用如下注释将正则表达式分散在多行中:
在这里插入图片描述
请注意前面的示例如何使用三引号语法 (‘’') 创建多行字符串,以便您可以将正则表达式定义分散到多行中,从而使其更加清晰。
正则表达式字符串内的注释规则与常规 Python 代码相同:# 符号及其后面到行尾的所有内容都将被忽略。此外,正则表达式的多行字符串内的额外空格不被视为要匹配的文本模式的一部分。这使您可以组织正则表达式,使其更易于阅读。

Combining re.IGNORECASE, re.DOTALL, and re.VERBOSE

What if you want to use re.VERBOSE to write comments in your regular expression but also want to use re.IGNORECASE to ignore capitalization? Unfortunately, the re.compile() function takes only a single value as its second argument. You can get around this limitation by combining the re.IGNORECASE, re.DOTALL, and re.VERBOSE variables using the pipe character (|), which in this context is known as the bitwise or operator.

So if you want a regular expression that’s case-insensitive and includes newlines to match the dot character, you would form your re.compile() call like this:
在这里插入图片描述

这种语法有点过时,源自 Python 的早期版本。位运算符的详细信息超出了本书的范围,但请查看 https://nostarch.com/automatestuff2/ 上的资源以获取更多信息。您还可以为第二个参数传递其他选项;它们并不常见,但您也可以在资源中阅读有关它们的更多信息。

Project: Phone Number and Email Address Extractor

假设您有一项无聊的任务:在长网页或文档中查找每个电话号码和电子邮件地址。如果您手动滚动页面,您可能会搜索很长时间。但是,如果您有一个程序可以在剪贴板中的文本中搜索电话号码和电子邮件地址,则只需按 CTRL-A 选择所有文本,按 CTRL-C 将其复制到剪贴板,然后运行您的程序。它可以用它找到的电话号码和电子邮件地址替换剪贴板上的文本。
每当您处理一个新项目时,您都会很想直接开始编写代码。但通常情况下,最好退后一步,考虑更大的前景。我建议首先为您的程序需要做什么制定一个高级计划。现在先不要考虑实际的代码——您可以稍后再考虑。现在,坚持大纲。
例如,您的电话和电子邮件地址提取器需要执行以下操作:

  1. 将文本从剪贴板中取出。
  2. 查找文本中的所有电话号码和电子邮件地址。
  3. 将它们粘贴到剪贴板上。

现在您可以开始思考这在代码中如何工作。该代码需要执行以下操作:
使用pyperclip模块复制和粘贴字符串。

  1. 创建两个正则表达式,一个用于匹配电话号码,另一个用于匹配电子邮件地址。
  2. 查找两个正则表达式的所有匹配项,而不仅仅是第一个匹配项。
  3. 将匹配的字符串整齐地格式化为单个字符串以进行粘贴。
  4. 如果在文本中未找到匹配项,则显示某种消息。
    该列表就像该项目的路线图。在编写代码时,您可以分别关注其中的每个步骤。每个步骤都相当易于管理,并且用您已经知道如何在 Python 中执行的操作来表达。
Step 1: Create a Regex for Phone Numbers

首先,您必须创建正则表达式来搜索电话号码。创建一个新文件,输入以下内容,并将其另存为 phoneAndEmail.py
在这里插入图片描述
TODO 注释只是程序的骨架。当您编写实际代码时,它们将被替换。
电话号码以可选的区号开头,因此区号组后跟一个问号。由于区号可以仅为三位数字(即 \d{3})或括号内的三位数字(即 (\d{3})),因此您应该使用管道连接这些部分。您可以将正则表达式注释 # Area code 添加到多行字符串的这一部分,以帮助您记住什么 (\d{3}|(\d{3}))?应该匹配。
电话号码分隔符可以是空格 (\s)、连字符 (-) 或句点 (.),因此这些部分也应该用管道连接。正则表达式的接下来的几个部分很简单:三个数字,后跟另一个分隔符,然后是四个数字。最后一部分是可选的扩展名,由任意数量的空格组成,后跟 ext、x 或 ext.,后跟两到五位数字。
Note
很容易与包含带括号 ( ) 和转义括号 ( ) 的组的正则表达式混淆。如果您收到“缺少 )、未终止的子模式”错误消息,请记住仔细检查您使用的是否正确。

Step 2: Create a Regex for Email Addresses

您还需要一个可以匹配电子邮件地址的正则表达式。使您的程序如下所示:
在这里插入图片描述
电子邮件地址 ➊ 的用户名部分是一个或多个字符,可以是以下任意一种:小写和大写字母、数字、点、下划线、百分号、加号或连字符。您可以将所有这些放入一个字符类中:[a-zA-Z0-9._%±]。
域名和用户名由 @ 符号 ➋ 分隔。域名 ➌ 的字符类稍微宽松一些,仅包含字母、数字、句点和连字符:[a-zA-Z0-9.-]。最后是“dot-com”部分(技术上称为顶级域),它实际上可以是任何点。这是两个到四个字符之间。
电子邮件地址的格式有很多奇怪的规则。此正则表达式不会匹配所有可能的有效电子邮件地址,但它会匹配您遇到的几乎所有典型电子邮件地址。

Step 3: Find All Matches in the Clipboard Text

现在您已经指定了电话号码和电子邮件地址的正则表达式,您可以让 Python re 模块完成查找剪贴板上所有匹配项的艰苦工作。 pyperclip.paste() 函数将获取剪贴板上文本的字符串值,findall()正则表达式方法将返回元组列表。
使您的程序如下所示:
在这里插入图片描述
每个匹配项都有一个元组,每个元组包含正则表达式中每个组的字符串。请记住,组 0 匹配整个正则表达式,因此元组索引 0 处的组是您感兴趣的组。
正如您在 ➊ 中看到的,您将把匹配项存储在名为 matches 的列表变量中。它以一个空列表和几个 for 循环开始。对于电子邮件地址,您附加每个匹配项的第 0 组 ➌。对于匹配的电话号码,您不想只附加组 0。虽然程序检测多种格式的电话号码,但您希望附加的电话号码采用单一标准格式。 phoneNum 变量包含一个由匹配文本 ➋ 的第 1、3、5 和 8 组构建的字符串。 (这些组是区号、前三位数字、后四位数字和分机号。)

Step 4: Join the Matches into a String for the Clipboard

现在您已将电子邮件地址和电话号码作为匹配项中的字符串列表,您希望将它们放在剪贴板上。 pyperclip.copy() 函数仅接受单个字符串值,而不是字符串列表,因此您可以在匹配时调用join()方法。
为了更容易地看到程序正在运行,让我们将找到的任何匹配项打印到终端。如果没有找到电话号码或电子邮件地址,程序应该告诉用户这一点。
使您的程序如下所示:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里开源低代码引擎 - Low-Code Engine

阿里开源低代码引擎 - Low-Code Engine 本文主要介绍如何在Windows运行/开发阿里开源低代码引擎 - Low-Code Engine 详细文档参见【 阿里开源低代码引擎 - Low-Code Engine 官方文档】 目录 阿里开源低代码引擎 - Low-Code Engine一、环境准备1、使用 WSL 在 Windows 上安装 L…

Java学习笔记2024/2/22

面向对象进阶部分学习方法&#xff1a; 特点&#xff1a; 逻辑性没有那么强&#xff0c;但是概念会比较多。 记忆部分重要的概念&#xff0c;理解课堂上讲解的需要大家掌握的概念&#xff0c;多多练习代码。 今日内容 复习回顾 static关键字 继承 教学目标 能够掌握st…

【开源】JAVA+Vue.js实现医院门诊预约挂号系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 功能性需求2.1.1 数据中心模块2.1.2 科室医生档案模块2.1.3 预约挂号模块2.1.4 医院时政模块 2.2 可行性分析2.2.1 可靠性2.2.2 易用性2.2.3 维护性 三、数据库设计3.1 用户表3.2 科室档案表3.3 医生档案表3.4 医生放号…

qml 保存当前界面并在其图片中添加文字

使用场景&#xff1a;在保存二维码的时候&#xff0c; 在二维码图片加标题或描述 保存后的图片 demo&#xff1a;https://download.csdn.net/download/uVarAndMethod/88868455

Electron实战之环境搭建

工欲善其事必先利其器&#xff0c;在进行实战开发的时候&#xff0c;我们最终的步骤是搞好一个舒服的开发环境&#xff0c;目前支持 Vue 的 Electron 工程化工具主要有 electron-vue、Vue CLI Plugin Electron Builder、electron-vite。 接下来我们将分别介绍基于 Vue CLI Plu…

暴雨信息|警惕AI 的变革阵痛与不稳定性

过去的未来主义幽灵使我们对数字化变革的预测保持谨慎。 我们现在经常听到&#xff0c;世界正处于一个技术转折点&#xff1b;我们正在快速步入一个由 ChatGPT 等人工智能工具塑造的未来。然而&#xff0c;我怀疑&#xff0c;2024 年我们将会被提醒到纳普斯特的幽灵——以及其他…

ChatGPT在数据分析岗位了解阶段的应用

ChatGPT在数据分析岗位了解阶段的应用 ​ 1.1 数据分析师的职责与技能要求 ​ 如果想成为数据分析师&#xff0c;首先要了解这个岗位的具体职责和技能要求。这个问题可以直接询问ChatGPT&#xff1a; ​ ChatGPT收到上述内容后&#xff0c;返回如下结果。 ​ ChatGPT给出的信…

【论文精读】Segment Anything

Segment Anything 前言Abstract1. Introduction2. Segment Anything Task3. Segment Anything Model4. Segment Anything Data Engine5. Segment Anything Dataset6. Segment Anything RAI Analysis7. Zero-Shot Transfer Experiments7.1. Zero-Shot Single Point Valid Mask E…

【开源】SpringBoot框架开发音乐平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示 四、核心代码4.1 查询单首音乐4.2 新增音乐4.3 新增音乐订单4.4 查询音乐订单4.5 新增音乐收藏 五、免责说明 一、摘要 1.1 项目介绍 基于微信小程序JAVAVueSpringBootMySQL的音乐平台&#xff0c;包含了音乐…

【ctfshow—web】——信息搜集篇1(web1~20详解)

ctfshow—web题解 web1web2web3web4web5web6web7web8web9web10web11web12web13web14web15web16web17web18web19web20 web1 题目提示 开发注释未及时删除 那就找开发注释咯&#xff0c;可以用F12来查看&#xff0c;也可以CtrlU直接查看源代码呢 就拿到flag了 web2 题目提示 j…

第3.5章:StarRocks数据导入——Broker Load

注&#xff1a;本篇文章阐述的是StarRocks-3.2版本的Broker Load导入机制 一、概述 Broker Load导入方式支持从HDFS类的外部存储系统&#xff08;例如&#xff1a;HDFS、阿里OSS、腾讯COS、华为云OBS等&#xff09;&#xff0c;支持Parquet、ORC、CSV、及 JSON 四种文件格式&a…

vue里echarts的使用:画饼图和面积折线图

vue里echarts的使用,我们要先安装echarts,然后在main.js里引入: //命令安装echarts npm i echarts//main.js里引入挂载到原型上 import echarts from echarts Vue.prototype.$echarts = echarts最终我们实现的效果如下: 头部标题这里我们封装了一个全局公共组件common-he…

qt 软件发布(Windows)

1. 开发环境 QtCreator MSVC编译器 2. 源码编译 生成release或者debug版本的exe可执行文件(x64或x86) 3. windeployqt 打包 ①左下角开始菜单栏找到QT的命令交互对话框&#xff0c;如下图MSVC 2017 64-bit(根据第二步编译的类型选择64位或者32位)。 ②cd 切换到第二步可…

TCP/IP协议详解

文章目录 TCP/IP协议概述基于TCP/IP协议的应用工具协议协议的必要性 TCP/IP协议TCP/IP协议族协议的分层 传输方式的分类报文、帧、数据包等的区别TCP 和 UDP的区别 TCP/IP协议概述 TCP/IP&#xff08;Transmission Control Protocol/Internet Protocol&#xff09;是一组通信协…

《图解HTTP》笔记2:http的构成

1&#xff0c;查看浏览器上面一个具体的http请求 浏览器地址栏输入网址&#xff1a;https://news.baidu.com/ 使用浏览器的开发者工具&#xff0c;查看网络中发送和接受的数据。 可以看到输入一个网址&#xff0c;浏览器和服务器进行了很多的交互。&#xff08;绿色部分&#…

python + selenium/appnium

Selenium 的自动化原理: selenium 自动化流程: 自动化程序调用Selenium 客户端库函数&#xff08;比如点击按钮元素&#xff09;客户端库会发送Selenium 命令 给浏览器的驱动程序浏览器驱动程序接收到命令后 ,驱动浏览器去执行命令浏览器执行命令浏览器驱动程序获取命令执行的…

OJAC近屿智能张立赛博士揭秘GPT Store:技术创新、商业模式与未来趋势

> - [Look&#xff01;&#x1f440;我们的大模型商业化落地产品](https://www.airecruitas.com/aigc) >- &#x1f4d6;更多AI资讯请&#x1f449;&#x1f3fe;[关注](https://mp.weixin.qq.com/s/85qwuIydaaydMQz2g0rgMA) >- [Free三天集训营助教在线为您火热答疑…

多任务爬虫(多线程和多进程)

在一台计算机中&#xff0c;我们可以同时打开多个软件&#xff0c;例如同时浏览网页、听音乐、打字等&#xff0c;这是再正常不过的事情。但仔细想想&#xff0c;为什么计算机可以同时运行这么多软件呢? 这就涉及计算机中的两个名词&#xff1a;多进程和多线程。 同样&#xf…

通信入门系列——锁相环、平方环、Costas环

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 本节目录 一、锁相环 1、压控振荡…

使用k-近邻算法改进约会网站的配对效果(kNN)

目录 谷歌笔记本&#xff08;可选&#xff09; 准备数据&#xff1a;从文本文件中解析数据 编写算法&#xff1a;编写kNN算法 分析数据&#xff1a;使用Matplotlib创建散点图 准备数据&#xff1a;归一化数值 测试算法&#xff1a;作为完整程序验证分类器 使用算法&…