Использование Regex для поиска строки, если она сначала не найдет другую строку - PullRequest
0 голосов
/ 12 января 2020

Здравствуйте. Я пытаюсь использовать регулярное выражение для поиска по файлу уценки по дате и получить совпадение только в том случае, если он находит экземпляр указанной строки c до того, как найдет другую дату.

Это это то, что у меня есть сейчас, и это определенно не работает. (\d{2}\/\d{2}\/\d{2})(string)?(^(\d{2}\/\d{2}\/\d{2}))

Таким образом, в этом случае будет выбрано совпадение, так как строка предшествует следующей дате:

01/20/20

string

01/21/20

Здесь не должно совпадать, поскольку строка находится после следующей даты :

01/20/20

this isn't the phrase you're looking for

01/21/20

string

Любая помощь по этому вопросу будет принята с благодарностью.

Ответы [ 2 ]

1 голос
/ 12 января 2020

Вы можете сопоставить дату как образец. Затем используйте закаленный жадный жетон подход (?:(?!\d{2}\/\d{2}\/\d{2}).)*, чтобы сопоставить string, не сопоставляя сначала другую дату.

Если вы сопоставили string, используйте не жадную точку .*? чтобы соответствовать первому вхождению следующей даты.

\d{2}\/\d{2}\/\d{2}(?:(?!\d{2}\/\d{2}\/\d{2}).)*string.*?\d{2}\/\d{2}\/\d{2}

Regex demo | Python demo

Например (используя re.DOTALL, чтобы точка соответствовала новой строке)

import re

regex = r"\d{2}\/\d{2}\/\d{2}(?:(?!\d{2}\/\d{2}\/\d{2}).)*string(?:(?!string|\d{2}\/\d{2}\/\d{2}).)*\d{2}\/\d{2}\/\d{2}"

test_str = """01/20/20\n\n"
    "string\n\n"
    "01/21/20\n\n"
    "01/20/20\n\n"
    "this isn't the phrase you're looking for\n\n"
    "01/21/20\n\n"
    "string"""

print(re.findall(regex, test_str, re.DOTALL))

Вывод

['01/20/20\n\n"\n\t"string\n\n"\n\t"01/21/20']

Если string не может произойти 2 раза между датами, вы можете использовать

\d{2}\/\d{2}\/\d{2}(?:(?!\d{2}\/\d{2}\/\d{2}|string).)*string(?:(?!string|\d{2}\/\d{2}\/\d{2}).)*\d{2}\/\d{2}\/\d{2}

Regex demo

Обратите внимание, что если вы этого не сделаете чтобы строка и даты были частью большего слова, можно добавить границы слов \b

1 голос
/ 12 января 2020

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

inp = """01/20/20

string                  # <-- this is matched

01/21/20

01/20/20

01/21/20

string"""               # <-- this is not matched

matches = re.findall(r'01/20/20(?:(?!\b01/21/20\b).)*?(\bstring\b).*?\b01/21/20\b', inp, flags=re.DOTALL)
print(matches)

Это печатает string только один раз, что соответствует первому вхождению, которое законно находится между начальной и конечной датами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...