Python: используйте Regex для сопоставления номера телефона и кортежа печати (с ограничениями форматирования)
Я хочу написать код, который может анализировать американские телефонные номера (например, «(664) 298-4397»). Ниже приведены ограничения:
- разрешить начальные и конечные пробелы
- разрешить пробелы между кодом города и местными номерами
- без пробелов в коде города или семизначном номере XXX-XXXX
В конечном итоге я хочу напечатать кортеж строк (area_code, first_three_digits_local, last_four_digits_local)
У меня две группы вопросов.
Вопрос 1: Ниже приведены входные данные, которые мой код должен принять и распечатать для:
- '(664) 298-4397', '(664)298-4397', '(664) 298-4397'
Ниже приведен код, который я пробовал:
regex_parse1 = re.match(r'^([\s]*[(]*[0-9]*[)]*[\s]*)+([\s]*[0-9]*)-([0-9]*[\s]*)$', '(664) 298-4397')
print (f' groups are: {regex_parse1.groups()} \n')
regex_parse2 = re.match(r'^([\s]*[(]*[0-9]*[)]*[\s]*)+([\s]*[0-9]*)-([0-9]*[\s]*)$', '(664)298-4397')
print (f' groups are: {regex_parse2.groups()} \n')
regex_parse3 = re.match(r'^([\s]*[(]*[0-9]*[)]*[\s]*)+([\s]*[0-9]*)-([0-9]*[\s]*)$', ' (664) 298-4397')
print (f' groups are: {regex_parse3.groups()}')
Строковый ввод для всех трех действителен и должен возвращать кортеж:
('664', '298', '4397')
Но вместо этого я получаю результат ниже для всех трех:
groups are: ('', '', '4397')
Что я делаю не так?
Вопрос 2: Следующие два фрагмента кода должны выводить объект «NoneType», у которого нет ошибки «группа» атрибутов, поскольку строка входного номера телефона нарушает ограничения. Но вместо этого я получаю результаты для всех трех.
regex_parse4 = re.match(r'^([\s]*[(]*[0-9]*[)]*[\s]*)+([\s]*[0-9]*)-([0-9]*[\s]*)$', '(404)555 -1212')
print (f' groups are: {regex_parse4.groups()}')
regex_parse5 = re.match(r'^([\s]*[(]*[0-9]*[)]*[\s]*)+([\s]*[0-9]*)-([0-9]*[\s]*)$', ' ( 404)121-2121')
print (f' groups are: {regex_parse5.groups()}')
Ожидаемый результат: должна быть ошибка, но вместо этого я получаю это для всех трех:
groups are: ('', '', '2121')
Что не так с моим кодом регулярного выражения?
2 ответа
Пытаться:
regex_parse4 = re.match(r'([(]*[0-9]{3}[)])\s*([0-9]{3}).([0-9]{4})', number)
Предполагается, что в скобках указан трехзначный код города, после которого следует XXX-XXXX.
Python возвращает «NoneType», если совпадений нет.
Если приведенное выше не работает, вот полезный инструмент для регулярных выражений:https://regex101.com
Редактировать:
Еще одно предложение - очистить данные перед применением нового регулярного выражения. Это помогает с случаями ненормального интервала, избавляется от круглых скобок и «-».
clean_number = re.sub("[^0-9]", "", original_number)
regex_parse = re.match(r'([0-9]{3})([0-9]{3})([0-9]{4})', clean_number)
print(f'groups are: {regex_parse}.groups()}')
>>> ('xxx', 'xxx', 'xxxx')
В общем, ваше регулярное выражение чрезмерно использует звездочку
*
. Подробности следующие:
У вас есть 3 группы захвата:
-
([\s]*[(]*[0-9]*[)]*[\s]*)
-
([\s]*[0-9]*)
-
([0-9]*[\s]*)
Вы используете звездочку для каждого элемента, включая открывающую и закрывающую круглые скобки. На самом деле почти все в вашем регулярном выражении цитируется звездочкой. Таким образом, группы захвата соответствуют также нулевым строкам . Вот почему ваши первая и вторая группы захвата возвращают нулевые строки. Единственный элемент, который вы не используете, - это знак дефиса.
-
непосредственно перед третьей группой захвата. Это также причина, по которой ваше регулярное выражение может захватывать третью группу захвата, как в
4397
и
2121
Чтобы решить вашу проблему, вы должны использовать звездочку только при необходимости.
На самом деле, вашему регулярному выражению еще есть над чем работать. Например, теперь он соответствует числовым цифрам любой длины (вместо блоков из 3 или 4 цифр). Это также позволяет код города не заключать в круглые скобки (из-за того, что вы используете звездочку вокруг символов скобок.
Для такого обычного регулярного выражения я предлагаю вам не изобретать велосипед. Вы можете обратиться к некоторым уже созданным регулярным выражениям, которые легко найти в Интернете. Например, вы можете обратиться к этому сообщению. Хотя сообщение использует javascript вместо Python, регулярное выражение аналогично.