首页 > 解决方案 > 无法理解为什么加入 re.findall 的索引从 1 而不是 0 开始

问题描述

《用python自动化无聊的东西》一书中的代码

#! python3
# phoneAndEmail.py - Finds phone numbers and email addresses on the clipboard.

import pyperclip, re

phoneRegex = re.compile(r'''(
    (\d{3}|\(\d{3}\))?                # area code
    (\s|-|\.)?                        # separator
    (\d{3})                           # first 3 digits
    (\s|-|\.)                         # separator
    (\d{4})                           # last 4 digits
    (\s*(ext|x|ext.)\s*(\d{2,5}))?    # extension
    )''', re.VERBOSE)

# Create email regex.
emailRegex = re.compile(r'''(
    [a-zA-Z0-9._%+-]+      # username
    @                      # @ symbol
    [a-zA-Z0-9.-]+         # domain name
    (\.[a-zA-Z]{2,4})      # dot-something
    )''', re.VERBOSE)

 # Find matches in clipboard text.
text = str(pyperclip.paste())
matches = []

for groups in phoneRegex.findall(text):
       phoneNum = '-'.join([groups[1], groups[3], groups[5]])
       if groups[8] != '':
           phoneNum += ' x' + groups[8]
       matches.append(phoneNum)
for groups in emailRegex.findall(text):
       matches.append(groups[0])

# Copy results to the clipboard.
if len(matches) > 0:
    pyperclip.copy('\n'.join(matches))
    print('Copied to clipboard:')
    print('\n'.join(matches))
else:
    print('No phone numbers or email addresses found.')

它会删除剪贴板中的电子邮件和电话号码。我的问题是线条

for groups in phoneRegex.findall(text):
       phoneNum = '-'.join([groups[1], groups[3], groups[5]])

如果我理解正确,findall 方法会返回一个元组列表,其中每个元组都有每组正则表达式,例如

[(area code, separator, first 3 digits, separator, last 4 digits, extension), (area code, separator, first 3 digits, separator, last 4 digits, extension)]

但是由于列表和元组以索引 0 开头,并且我想加入每个元组项目的第一个、第三个和第五个项目,为什么不是那行

for groups in phoneRegex.findall(text):
       phoneNum = '-'.join([groups[0], groups[2], groups[4]])

标签: pythonregex

解决方案


在python(老实说,以及大多数其他正则表达式引擎)中,re match对象在成功匹配后总是至少有一个组。其中第一个(第 0 个索引)始终是完全匹配

为了说明我所说的“完全匹配”是什么意思。这是这个简单的正则表达式 - r'hello\s+world'。这将匹配字符串,例如hello worldandhello world和 even foo hello world bar。查看演示

现在该演示将有 3 个匹配项,在所有这些匹配项中,您会注意到右侧显示“完全匹配”并列出了匹配项,第一个字符串是hello world,第二个是hello world,第三个是hello world

是完整的比赛。这只是完整的正则表达式匹配,没有任何捕获。

现在这是另一个匹配捕获-的正则表达式r'hello\s+(world)'。检查这个演示

现在请注意,每场比赛有 2 个字段,一个是full match,与上次相同,另一个是Group 1。这是我们捕获的组 - world

总之,成功匹配后,完整匹配始终位于第 0 个索引处,然后是捕获的组。

阅读文档以获取更多信息。


推荐阅读