Как найти в тексте строго трехзначное число?

Мне нужно определять из текста строго трехзначное число.

Пробовал:

re.findall('[0-9]{3}', '1234')

Выводит "123", а мне нужно, чтобы ничего не выводило, т.к. число четырехзначное.

Либо, если текст такой "123-123", то нужно, чтобы тоже ничего не выводило.

Какой способ посоветуете?


Ответы (3 шт):

Автор решения: ipatev_nn

Пример: regex101

(?:(?<=[^\w-])|(?<=^))\d{3}(?:(?=[^\w-])|(?=$))

Устанавливаем границы самостоятельно. Как в комментариях указали - \b указывает на границы слова, здесь определяем границы слова самостоятельно.
(?<=[^\w-])|(?<=^) - позитивный просмотр назад, либо все символы, кроме цифр, букв, нижнего подчеркивания и тире, либо начало строки. Далее захват 3 цифр, после чего аналогично построенный позитивный просмотр вперед. В случае, если нужно будет ограничить символы, после которых не должен быть захват 3х цифр, прописывать как раз в этих группах.

→ Ссылка
Автор решения: Wiktor Stribiżew

Решением будет такое выражение, которое найдёт 3-значное число между пробельными символами или началом/концом строки (т.е. с использованием пробельных границ):

re.findall(r'(?<!\S)[0-9]{3}(?!\S)', '987 6781 t 444 t 1234 zzz 453')
# => ['987', '444', '453']

Хотя, в таком случае, зачем нужны регулярные выражения?

[x for x in '987 6781 t 444 t 1234 zzz 453'.split() if len(x) == 3 and all(z.isdigit() for z in x)]
# => ['987', '444', '453']

Если границы не пробельные, а....

  • дефисно-цифровые: re.findall(r'(?<![-\d])[0-9]{3}(?![-\d])', '-987 123-123 444- t 1234 zzz 453') => ['453']
  • не между цифрами или цифрой+дефисом или дефисом+цифрой: re.findall(r'(?<!\d)(?<!\d-)[0-9]{3}(?!-?\d)', '-987 123-123 444- t 1234 zzz 453') => ['987', '444', '453']

Дополнительно

Очень часто пользователи, спрашивающие, как проверить строку на строгое соответсвтие шаблону, имеют в виду:

  • Полное соответствие строки шаблону: bool(re.fullmatch(r'[0-9]{3}', '123')) => True (ещё re.match(r'[0-9]{3}$', '123') и re.search(r'^[0-9]{3}$', '123'))
  • Не между буквами/цифрами/знаком подчёркивания: re.findall(r'\b[0-9]{3}\b', '123,456,12345,b123,876_') => ['123', '456']
  • Не между буквами/цифрами (исключая знак подчёркивания): re.findall(r'(?<![^\W_])[0-9]{3}(?![^\W_])', '123,456,12345,b123,876_') => ['123', '456', '876']
  • Не в дробных числах: re.findall(r'(?<!\d)(?<!\d[.,])[0-9]{3}(?![.,]?\d)', '987.564 123-123 444,1234--453.') => ['123', '123', '453'] (удалите либо символ точки, либо запятой по вашему усмотрению).
→ Ссылка
Автор решения: Qwertiy

Думаю, как-то так:

re.findall('\b(?<!-)[0-9]{3}(?!-)\b', '1234')
→ Ссылка