Regex для соответствия набора слов, которому не предшествует, в пределах 25 символов, другой набор слов - PullRequest
0 голосов
/ 13 апреля 2020

Я хотел бы написать регулярное выражение, чтобы соответствовать набору слов (предложил / дал мне работу), которому не предшествует, в пределах 25 символов, другой набор слов (не, не будет, и т. Д. c) в том же предложении. Я более или менее понимаю, как получить группу слов, но я не могу понять, почему отрицательный взгляд здесь не работает. Кроме того, мне нужно выполнить sh это только в одном регулярном выражении, и я использую python для их проверки. Вот несколько примеров совпадений / несоответствий:

Match:
he offered me a job
she gave me a job

Does not match:
he did not even offer me a job
she would not give me a job
he did not think about offering me a job

Вот мое регулярное выражение: (?<!did not)[^\.\n]{0,25}(?:(?:offer(ed|ing|s)?|g[ai]ves?)[^\.\n\!\?]{0,25}(?:job))

А вот ссылка regex101 .

1 Ответ

1 голос
/ 13 апреля 2020

Я предположил, что проблема заключается в совпадении строки "ab" или "cd" при условии, что ей не предшествует строка длиной менее 10 символов "ef" или "gh".

Я должен сделайте предположение о структуре строки: если "ef" или "gh" предшествует "ab" или "cd", а последний предшествует "ef" или "gh", за последним не следует "ab" или "cd".

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

(?:ef|gh).{0,9}(?:ab|cd)(?!.*(?:ab|cd))|(ab|cd)(?!.*(?:ab|cd))

Демо

Я использовал то, что было названо "величайшим трюком с регулярными выражениями" .

Обратите внимание, что регулярное выражение имеет форму X|(Y). Если X соответствует, группа захвата 1 пуста. Если X не соответствует, группа захвата 1 будет содержать последний экземпляр в строке строки "ab" или "cd".

X является выражением, которое, если соответствует, означает, что нет строки "ab" или "cd", которая следует за строкой "cd" или "ef" по крайней мере на 10 символов.

Поэтому мы игнорируем то, что соответствует, и исследуем только группу захвата 1. Если она пуста, цель терпит неудачу; если не пусто, цель успешно выполняется, цель состоит в том, чтобы найти последний экземпляр строки "ab" или "cd", которому не предшествует "cd" или "ef" или который следует за последний предшествующий "cd" или "ef" не менее чем из 10 символов.

Модуль регулярных выражений выполняет следующие операции.

(?:ef|gh)       # match 'ef' or 'gh'
.{0,9}          # match 0-9 characters
(?:ab|cd)       # match 'ab' or 'cd'
(?!             # begin a negative lookahead
  .*            # match 0+ characters
  (?:ab|cd)     # match 'ab' or 'cd' 
)               # end negative lookahead 
|               # or
(ab|cd)         # match 'ab' or 'cd' 
(?!.*(?:ab|cd)) # match is to not be followed later in the line by 'ab' or 'cd'

отрицательный прогноз, (?!.*(?:ab|cd)), который появляется дважды, гарантирует, что предыдущее совпадение "ab" или "cd", если оно есть, является последним экземпляром любой строки в строке.

Как обычно, если несколько Строки должны соответствовать небольшим изменениям. Я написал регулярное выражение для сопоставления в строках, чтобы продемонстрировать влияние регулярного выражения для нескольких строк в связанном онлайн-тестере регулярных выражений.

...