Цифровые форматы извлечения регулярных выражений Python

#python #regex

Вопрос:

Я пытаюсь извлечь уникальные идентификаторы счетов-фактур из таких строк:

 1) Payment of invoice nr.2021-3-5450
2) Invoice 2021 3 27 has been paid
 

Слова могут меняться, но формат идентификатора счета-фактуры всегда:

  - YEAR-MONTH-CUSTOMER_ID, or
 - YEAR MONTH CUSTOMER_ID
 

Идентификатор пользователя может быть от 1 до 9999.

Я уже пробовал это:

 m = re.search(r"d ", s)
 

Но он возвращается только в 2021 году. Есть ли способ, которым я могу записать все числа в вышеуказанных форматах?

Комментарии:

1. Пожалуйста, обновите, чтобы показать работу, которую вы пытались выполнить до сих пор (или, по крайней мере, минимальный код, с которым вы пытались работать).

2. Спасибо за предложение @rv.kvetch, я обновил вопрос.

3. re.findall(r'd ', s) работает на тебя.

4. да, это действительно хороший момент. что-то настолько простое должно действительно сработать. однако в ОП не было слишком ясно, нужно ли регулярному выражению выполнять проверку, например, проверять, не превышает ли customer_id максимальное значение (9999), например. Если ответ отрицательный, то этот ответ действительно работает идеально.

Ответ №1:

Попробуйте это на игровой площадке регулярных выражений: Ссылка

Регулярное выражение: ([d]{4})[- ](0?[1-9]|1[0-2])[- ](d{1,4})b

Пояснение: Соответствует году в виде 4-значного числа, месяцу в виде целого числа от 1 до 12 (включая начальные нули) и идентификатору клиента в виде целого числа от 0 до 9999; значения могут быть разделены либо тире, либо пробелами. Группы будут захвачены (year, month, customer_id) в таком порядке.


Демо-версия Python:

 import re
from typing import Optional, NamedTuple


invoice_re = re.compile(r'([d]{4})[- ](0?[1-9]|1[0-2])[- ](d{1,4})b')

# NamedTuple that contains the invoice data
Invoice = NamedTuple('Invoice', year=int, month=int, customer_id=int)


def parse_invoice(invoice: str) -> Optional[Invoice]:
    """Parse an invoice, and return a tuple of (year, month, customer_id)"""
    result = invoice_re.search(invoice)
    return Invoice(*map(int, result.groups())) if result else None


s1 = 'Payment of invoice nr.2021-3-5450'
s2 = 'Invoice 2021 3 27 has been paid'

print(parse_invoice(s1))
print(parse_invoice(s2))