Регулярное выражение для захвата перекрывающихся совпадений, предшествующих любому числу с более чем 4 цифрами

Я пишу регулярное выражение, чтобы выбрать 30 символов перед числом, которое содержит более 4 цифр в нижеследующем тексте. Вот мой код:

text = "I went and I bought few tickets and ticket numbers 100000,100001 and 100002.I bought them for 200,300 and 400 USD. Box office collections were 55555555 USD"

reg=".{0,30}(?:[\d]+[ .]?){5,}"
regc=re.compile(reg)
res=regc.findall(text)

Это дает ниже частичные результаты

enter image description here

Я получаю 30 символов только перед 100000.

Как получить 30 символов до 100001 и как получить 30 символов до 100002?

Каковы ожидаемые результаты? При попытке исправить это получил ['D. Box office collections were 55555555', 'cket numbers 100000,100001 and 100002', 'ets and ticket numbers 100000,100001', 'few tickets and ticket numbers 100000']

Wiktor Stribiżew 31.10.2018 14:10

Вам нужно использовать регулярное выражение для захвата символов, которые предшествуют всем числам с более чем 4 цифрами в вашей строке?

benvc 31.10.2018 14:19

@Wiktor да, это поможет .. Также вы можете помочь мне извлечь 100001 и 100002 вместе со 100000, как в первой строке ..

crazy_dd 31.10.2018 14:32

@benvc да, я хочу захватывать символы до 4-значного числа

crazy_dd 31.10.2018 14:34
3
4
65
3

Ответы 3

Вы ищете любые 30 символов впереди, кроме разрывов строк,? = Положительный взгляд в будущее, но не включаемый в группу захвата

/.{30}(?=100001)/g

https://regexr.com/4293v

Поскольку вам нужны совпадающие совпадения, вам нужно использовать поисковые запросы. Однако ретроспективный просмотр в re имеет фиксированную ширину, поэтому вы можете использовать хитрость: перевернуть строку, использовать регулярное выражение с опережением, а затем отменить совпадения:

import re
rev_rx = r'((?:\d+[ .]?){5,})(?=(.{0,30}))'
text="I went and I bought few tickets and ticket numbers 100000,100001 and 100002.I bought them for 200,300 and 400 USD. Box office collections were 55555555 USD"
results = [ "{}{}".format(y[::-1], x[::-1]) for x, y in re.findall(rev_rx, text[::-1]) ]
print(results)
# => ['D. Box office collections were 55555555', 'cket numbers 100000,100001 and 100002', 'ets and ticket numbers 100000,100001', 'few tickets and ticket numbers 100000']

См. Демо Python.

Регулярное выражение ((?:\d+[ .]?){5,})(?=(.{0,30})) соответствует и захватывает в Группу 1 пять или более последовательностей из 1+ цифр и необязательного пробела или запятой. Затем положительный просмотр вперед проверяет, есть ли в строке от 0 до 30 символов. Подстрока заносится в группу 2. Итак, все, что вам нужно, это объединить перевернутые значения группы 2 и группы 1, чтобы получить нужные совпадения.

Вы можете сделать это, объединив простое регулярное выражение со строковыми методами, чтобы получить 30 символов, предшествующих любому числу с более чем 4 цифрами (вместо использования более сложного регулярного выражения для поиска совпадений и захвата желаемых символов).

В приведенном ниже примере используется регулярное выражение для поиска всех чисел, состоящих более чем из 4 цифр, а затем используется str.find() для получения позиции каждого совпадения в исходном тексте, чтобы вы могли разрезать предыдущие 30 символов:

import re

text = "I went and I bought few tickets and ticket numbers 100000,100001 and 100002.I bought them for 200,300 and 400 USD. Box office collections were 55555555 USD"

patt = re.compile(r'\d{5,}')
nums = patt.findall(text)
matches = [text[:text.find(n)][-30:] for n in nums]

print(matches)
# OUTPUT (shown on multiple lines for readability)
# [
#     'ew tickets and ticket numbers ',
#     'ets and ticket numbers 100000,',
#     'ket numbers 100000,100001 and ',
#     '. Box office collections were '
# ]

Другие вопросы по теме