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

news2024/11/14 18:03:47

目录

    • 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 False
     for i in range(0, 3):if not text[i].isdecimal():
             return Falseif text[3] != '-':
         return False
     for i in range(4, 7):if not text[i].isdecimal():
             return Falseif text[7] != '-':
         return False
     for 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.coloradmin.cn/o/1464362.html

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

相关文章

基于springboot+vue的酒店客房管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

【数据结构初阶 6】二叉树:堆的基本操作 + 堆排序的实现

文章目录 &#x1f308; Ⅰ 二叉树的顺序结构&#x1f308; Ⅱ 堆的概念与性质&#x1f308; Ⅲ 堆的基本操作01. 堆的定义02. 初始化堆03. 堆的销毁04. 堆的插入05. 向上调整堆06. 堆的创建07. 获取堆顶数据08. 堆的删除09. 向下调整堆10. 判断堆空 &#x1f308; Ⅳ 堆的基本…

【Git企业实战开发】Git常用开发流操作总结

【Git企业实战开发】Git常用开发流操作总结 大家好 我是寸铁&#x1f44a; 总结了一篇Git常用开发流操作总结的文章✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 现在刚做项目的伙伴&#xff0c;可能你之前学过git&#xff0c;但是一实战发现不熟悉 没关系&#xff0c;看寸铁这篇…

色彩搭配:打造视觉吸引力与用户体验的关键

title: 色彩搭配&#xff1a;打造视觉吸引力与用户体验的关键 date: 2024/2/22 12:01:11 updated: 2024/2/22 12:01:11 tags: 网站色彩搭配视觉吸引力品牌形象用户体验设计色彩心理学配色技巧色轮互补 在当今数字化时代&#xff0c;网站已经成为了人们获取信息、进行交流和进行…

fatal error: costmap_2d/keepOutZone.h

fatal error: costmap_2d/keepOutZone.h: No such file or directory 7 | #include "costmap_2d/keepOutZone.h" 解决&#xff1a; #include "costmap_plugins/keepOutZone.h"代码中搜索 costmap_2d&#xff0c;全部替换成costmap_plugins&#xff1b…

【Unity】Unity与安卓交互

问题描述 Unity和安卓手机进行交互&#xff0c;是我们开发游戏中最常见的场景。本教程将从一个简单的例子来演示一下。 本教程需要用到Android Studio2021.1.1 1.Android Studio新建一个工程 2.选择Empty Activity 然后点击Next 3.点击Finish完成创建 4.选择File-New-New Mo…

Less预处理器教程

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes 觉得有帮助的同学&#xff0c;可以点心心支持一下哈 一、Less介绍 less官方文档 lesscss.org/ less中文文档 less.bootcss.com/ less是一种css预处理器&#xff0c;它扩展了css语言&#xff0c…

用Python插入页码到PDF文档

页码是许多类型文件中的重要内容&#xff0c;它能方便读者在文档中的导航。在创建PDF文档时&#xff0c;添加页码对于组织和引用内容特别有用。在本文中&#xff0c;我们将探讨如何利用Python程序高效地插入页码到PDF文档中&#xff0c;简化工作流程并创建出精美、结构合理的PD…

Eureka注册中心(黑马学习笔记)

Eureka注册中心 假如我们的服务提供者user-service部署了多个实例&#xff0c;如图&#xff1a; 大家思考几个问题&#xff1a; order-service在发起远程调用的时候&#xff0c;该如何得知user-service实例的ip地址和端口&#xff1f; 有多个user-service实例地址&#xff0c…

从 Elasticsearch 到 Apache Doris,统一日志检索与报表分析,360 企业安全浏览器的数据架构升级实践

导读&#xff1a;随着 360 企业安全浏览器用户规模的不断扩张&#xff0c;浏览器短时间内会产生大量的日志数据。为了提供更好的日志数据服务&#xff0c;360 企业安全浏览器设计了统一运维管理平台&#xff0c;并引入 Apache Doris 替代了 Elasticsearch&#xff0c;实现日志检…

Sulfo Cyanine3 dCTP,磺化-Cy3-dCTP,可以实时监测DNA的合成过程

Sulfo-Cy3-dCTP&#xff0c;Sulfo Cyanine3 dCTP&#xff0c;磺化-Cy3-dCTP&#xff0c;可以实时监测DNA的合成过程 您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;Sulfo-Cy3-dCTP&#xff0c;Sulfo Cyanine3 dCTP&#xff0c;磺化-Cy3-dCTP 一、基本信息 产品简…

隐藏饿了么el-select组件的el-select-dropdown部分,只使用el-select的显示框

隐藏饿了么el-select组件的el-select-dropdown部分,只使用el-select的显示框 问题: 由于el-select组件的el-select-dropdown部分是自动插入在最外层Body上的&#xff0c;所以在当前组件的scoped中让el-select-dropdown组件display:none不会生效所以需要&#xff1a; :popper-…

企业数字化转型必备:大数据如何助力企业腾飞?

随着数字技术的迅猛发展&#xff0c;企业数字化转型已经成为一种不可逆转的趋势。在这个过程中&#xff0c;大数据扮演了至关重要的角色。那么&#xff0c;大数据究竟如何助力企业腾飞呢&#xff1f;接下来&#xff0c;我们将从多个角度深入剖析。 一、大数据助力企业精准决策 …

【MySQL】数据库索引详解 | 聚簇索引 | 最左匹配原则 | 索引的优缺点

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

糖尿病性视网膜病变(DR)的自动化检测和分期

糖尿病性视网膜病变&#xff08;DR&#xff09;的自动化检测和分期 提出背景DR的阶段及其特征 历年解法计算机视觉方法多分类方法 新的解法深度学习方法迁移学习大模型多模型集成全流程分析 总结特征1&#xff1a;图像分割特征2&#xff1a;疾病分级特征3&#xff1a;治疗建议生…

邻接矩阵乘法 最短距离

问题一 最短距离 先从一个问题说起&#xff0c;输入 [4, 1, 4, 6, 4, 0, 6]代表依赖关系&#xff0c;从1开始&#xff0c;0代表ROOT节点。第二个元素为1代表第二个term在依赖树上的父节点为第1个term。​ 输出​ [[0 1 0 0 0 0 0]​ [0 0 0 0 0 0 0]​ [0 0 0 0 0 0 0]​ [1 …

【Java从入门到精通】Java Character 类

Java Character 类 Character 类用于对单个字符进行操作。 Character 类在对象中包装一个基本类型 char 的值 实例 char ch a;// Unicode 字符表示形式 char uniChar \u039A; // 字符数组 char[] charArray { a, b, c, d, e }; 然而&#xff0c;在实际开发过程中&#xf…

STM32—触摸键

目录 1 、 电路构成及原理图 2 、编写实现代码 3、代码讲解 4、烧录到开发板调试、验证代码 5、检验效果 此笔记基于朗峰 STM32F103 系列全集成开发板的记录。 1 、 电路构成及原理图 触摸键简单的了解就是一次电容的充放电过程。从原理图可以看出&#xff0c;触摸键 …

ORACLE数据库OCP认证

OCP证书是什么&#xff1f; OCP&#xff0c;全称Oracle Certified Professional&#xff0c;是Oracle公司的Oracle数据库DBA&#xff08;Database Administrator&#xff0c;数据库管理员)认证课程。这是Oracle公司针对数据库管理领域设立的一项认证课程&#xff0c;旨在评估和…

分类预测 | Matlab实现CWT-DSCNN-MSA基于时序特征、cwt小波时频图的双流卷积融合注意力机制的分类预测

分类预测 | Matlab实现CWT-DSCNN-MSA基于时序特征、cwt小波时频图的双流卷积融合注意力机制的分类预测 目录 分类预测 | Matlab实现CWT-DSCNN-MSA基于时序特征、cwt小波时频图的双流卷积融合注意力机制的分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab…