re.findall генерирует неожиданные лишние пробелы

1

Я построил такое регулярное выражение, следуя инструкциям

#Create phone regex
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)

Я тестировал его

In [91]: text 
Out[91]: '800-420-7240 415-863-9900 415-863-9950'
In [92]: phoneRegex.findall(text)
Out[92]: 
[('800-420-7240', '800', '-', '420', '-', '7240', '', '', ''),
 ('415-863-9900', '415', '-', '863', '-', '9900', '', '', ''),
 ('415-863-9950', '415', '-', '863', '-', '9950', '', '', '')]

В конце каждой группы есть три None, особенно последний из 415-863-9950 который не имеет пробелов.

Как могут генерироваться дополнительные пробелы?

  • 1
    '' - это пустая строка, а не None .
  • 2
    В вашем регулярном выражении девять групп захвата, поэтому в каждом результате из .findall() есть девять групп. Если вам не нужны все эти группы, измените их на группы без захвата - (?:...) вместо (...) . Или просто уберите круглые скобки, если они на самом деле ни для чего не нужны.
Показать ещё 2 комментария
Теги:

2 ответа

1
Лучший ответ

re.findall (pattern, string, flags = 0)

Верните все совпадающие совпадения шаблонов в строке, как список строк. Строка сканируется слева направо, а совпадения возвращаются в найденном порядке. Если одна или несколько групп присутствуют в шаблоне, верните список групп; это будет список кортежей, если шаблон имеет более одной группы. Пустые матчи включены в результате.

https://docs.python.org/2/library/re.html#re.findall

В вашем регулярном выражении у вас есть необязательная группа. то есть:

(\s*(ext|x|ext.)\s*(\d{2,5}))?

? подразумевает, что эта группа является необязательной, и благодаря этому findAll() возвращает None для всех несоответствующих групп. Вы можете, конечно, пометить группы как не захватывающие, добавив ?: Непосредственно перед вашей группой, но если вы это сделаете, вы не сможете захватить такие значения, как: 800-420-7240 ext 1112 415-863-9900 415-863-9950 (согласно последней группе, которая захватывает ext). [исправьте меня, если я ошибаюсь в этом последнем заявлении]

Однако вы можете удалить значения None и вернуть только допустимые группы с помощью небольшого обходного пути.

import 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)

matches = phoneRegex.findall('800-420-7240 ext 1112 415-863-9900 415-863-9950')
# matches = phoneRegex.findall('800-420-7240 415-863-9900 415-863-9950')

for i in matches:
    print filter(None, i)

Это даст результат как:

('800-420-7240 ext 1112', '800', '-', '420', '-', '7240', ' ext 1112', 'ext', '1112')
('415-863-9900', '415', '-', '863', '-', '9900')
('415-863-9950', '415', '-', '863', '-', '9950')

Надеюсь, поможет!! Пожалуйста, не стесняйтесь спрашивать, есть ли у вас какие-либо сомнения.

1

Как отмечает jasenharper в комментариях, пустые строки имеют место в пустых группах захвата. Самый простой способ избавиться от них - очистить список после применения регулярного выражения:

s = phoneRegex.findall(text)
s = [('800-420-7240', '800', '-', '420', '-', '7240', '', '', ''),
 ('415-863-9900', '415', '-', '863', '-', '9900', '', '', ''),
 ('415-863-9950', '415', '-', '863', '-', '9950', '', '', '')]

newS = []
for e in s:
    sl = list(filter(lambda x: x != "",e))
    newS.append(sl)
print(newS) # [['800-420-7240', '800', '-', '420', '-', '7240'], ['415-863-9900', '415', '-', '863', '-', '9900'], ['415-863-9950', '415', '-', '863', '-', '9950']]

Ещё вопросы

Сообщество Overcoder
Наверх
Меню