Не могу понять, почему индекс для присоединения к re.findall начинается с 1 вместо 0 - PullRequest
0 голосов
/ 10 июля 2020

Код из книги «Автоматизируйте скучные вещи с помощью 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]])

1 Ответ

2 голосов
/ 10 июля 2020

В python (и в большинстве других движков регулярных выражений, если честно), объекты re match всегда имеют хотя бы одну группу после успешного совпадения. Первый из них (0-й индекс) всегда является полным совпадением .

Чтобы проиллюстрировать, что я имею в виду под «полным совпадением». Вот это простое регулярное выражение - r'hello\s+world'. Это будет соответствовать таким строкам, как hello world и hello world и даже foo hello world bar. Посмотрите демо

Теперь в этой демоверсии будет 3 совпадения, и во всех из них вы заметите, что справа написано «полное совпадение» и указано совпадение. , что для первой строки - hello world, для второй - hello world, а для третьей - hello world

Это - полное совпадение. Это просто полное совпадение регулярного выражения без какого-либо захвата.

А вот еще одно регулярное выражение, которое соответствует и захватывает- r'hello\s+(world)'. Проверьте demo для этого.

Теперь обратите внимание, каждое совпадение имеет 2 поля, одно - это полное совпадение , которое совпадает с предыдущим, а другое это Группа 1 . Это наша захваченная группа - world.

В заключение, после успешного совпадения полное совпадение всегда находится по 0-му индексу, за которым следуют захваченные группы.

Прочтите документы для получения дополнительной информации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...