Извлечение текста между двумя похожими шаблонами с помощью регулярных выражений - PullRequest
0 голосов
/ 02 марта 2020

У меня есть текстовый файл, из которого я хочу извлечь текст между всеми заголовками. Небольшая часть текстового файла может быть доступна по следующей ссылке:

https://docs.google.com/document/d/1qgxkEpPvXNm_cpJaP4gmhkF-w2UOjeBynnxFvfzQNGM/edit?usp=sharing

Текст в том же порядке, как показано в ссылке. Заголовки указаны заглавными буквами, нумерация в том же формате, что и в ссылке. Они содержат только три специальных символа: &, /, и -. Кроме того, заголовкам предшествуют и следуют пустые строки, аналогичные тем, которые показаны в тексте в ссылке.

Я хочу извлечь текст между заголовками, например, между 3.0 ЗАДЕРЖКА БЕЗОПАСНОСТИ / ЗАДЕРЖКА ДЕНЕГ и 4.0 ЗАДАНИЕ МОБИЛИЗАЦИИ.

Я использую следующее регулярное выражение:

regex_clause_des=r'(^\d+[.][0]\s+(?:[-/&,]*\s*[A-Z]+\s*)+)(.*?)(?=(^\d+[.][0]\s+(?:[-/&,]*\s*[A-Z]+\s*)+))'

regex = re.compile(regex_clause_des, re.DOTALL)

re.findall(regex,contract_text)

Однако для его работы на процессоре 8-го поколения i5 требуется много времени (более 2 часов и он все еще работает).

Является ли регулярное выражение, которое я использую, правильным для нужного результата и есть ли другой способ получить результаты быстрее (возможно, с помощью другого регулярного выражения)?

Ожидаемый вывод - это список текста между заголовками.

1 Ответ

0 голосов
/ 02 марта 2020

Я полагаю, что сопоставление упреждающей части после каждого отдельного символа в ленивом (.*?) крайне неэффективно.

Попробуйте только сопоставить заголовки, а затем извлекать текст между двумя последовательными совпадениями:

import re
from itertools import tee, chain

s = """
3.0 SECURITY DEPOSIT/ RETENTION MONEY

3.1 The Security deposit or the retention money shall be deducted from each
running/ final bill of the contractor @ 2.5% (two point five per cent only) of the
gross value of the Running Account/ final bill.

4.0 MOBILIZATION ADVANCE

Mobilization advance up to maximum of amount as mentioned in the
“Memorandum (Annexure-I)” shall be paid to the contractor,
...

"""

header_regex = re.compile(r'^\d+\.0\s+[A-Z][A-Z0-9\s&,/-]*$', re.MULTILINE)

# https://docs.python.org/3/library/itertools.html#itertools-recipes
def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

for p in pairwise(chain(map(re.Match.span, header_regex.finditer(s)), [(len(s),)])):
    print('----- HEADING USED TO BE HERE -----')
    print(s[p[0][1]:p[1][0]].strip())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...