Вопрос о регулярном выражении - два отрицательных взгляда в одном выражении - PullRequest
1 голос
/ 31 января 2020

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

Я хочу иметь возможность извлекать слово уменьшенное из предложений, но не в том случае, если этому слову предшествует отрицательное выражение.

Например,

Sentences                                |Output
1. lv function is reduced                    reduced
2. lv function is not reduced                -
3. reduced lv function                       reduced
4. no evidence of reduced lv function        -

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

Однако для случаев 1 и 2 отрицательный взгляд не работает.

Вот предложения и текущий RegEx для проверки:

((?<!((no|not|none)(?:\D*?)))(reduced|depressed|normal)(?:\D*?))?(?:lv function|lv|systolic function|left ventricular ejection fraction)(((?:.*\bnot\b)(\D*))(reduced|depressed|normal))?

Sentences :
lv function is reduced   
lv function is not reduced 
reduced lv function
no evidence of reduced lv function   

В качестве альтернативы здесь есть ссылка: regexr.com / 4tc61

Кроме того, в конечном итоге я собираюсь работать в R.

Спасибо всем.

Ответы [ 2 ]

1 голос
/ 02 февраля 2020

Решение regex будет очень сложным, и вы можете использовать его, только если хорошо его понимаете. Я постараюсь объяснить это так хорошо, как только смогу.

Q : Как сопоставить что-то, чему не предшествует строка неизвестной длины, если мои видоискатели не поддерживают такие узоры? A : Сопоставьте то, что вам не нужно, пропустите сопоставленные тексты и go при сопоставлении с позиции, где совпадение не удалось .

Вы можете сделать это с регулярным выражением PCRE, которое поддерживает (*SKIP)(*FAIL) (или более короткую (*SKIP)(*F)) конструкцию.

Теперь посмотрите на шаблон:

(?:\b(?:no|not|none)\b\D*?\b(?:reduced|depressed|normal)\b\D*?\b(?:lv function|lv|systolic function|left ventricular ejection fraction)\b|\b(?:lv function|lv|systolic function|left ventricular ejection fraction)\b\D*?\bnot\b\D*?\b(?:reduced|depressed|normal)\b)(*SKIP)(*F)|(?:\b(reduced|depressed|normal)\b\D*?)?\b(?:lv function|lv|systolic function|left ventricular ejection fraction)\b(?:\D*?\b(reduced|depressed|normal)\b)?

Выглядит громоздко, но давайте go рассмотрим составляющие :

  • (?: - запуск группы без захвата, которая служит контейнером, (*SKIP)(*F) будет применяться ко всем альтернативам внутри него):
    • \b(?:no|not|none)\b\D*?\b(?:reduced|depressed|normal)\b\D*?\b(?:lv function|lv|systolic function|left ventricular ejection fraction)\b :
      • \b(?:no|not|none)\b - любое из слов в группе без захвата как целые слова
      • \D*? - 0+ non-di git chars
      • \b(?:reduced|depressed|normal)\b - любое из слов внутри группы без захвата как целые слова
      • \D*? - 0+ non-di git char
      • \b(?:lv function|lv|systolic function|left ventricular ejection fraction)\b - любой текст внутри группа без захвата как целые слова
    • | - или
    • \b(?:lv function|lv|systolic function|left ventricular ejection fraction)\b\D*?\bnot\b\D*?\b(reduced|depressed|normal)\b:
      • \b(?:lv function|lv|systolic function|left ventricular ejection fraction)\b - любой текст внутри группа без захвата как весь мир ds
      • \D*?\bnot\b\D*? - 0+ не цифр как можно меньше, целое слово not, 0+ не цифр как можно меньше
      • \b(?:reduced|depressed|normal)\b - любой текст внутри группы без захвата как целые слова
  • )(*SKIP)(*F) - конец группы контейнеров и глаголы PCRE, которые не соответствуют, создавая механизм регулярных выражений go для поиска совпадений, начиная с позиции, где совпадение не удалось
  • | - или (то есть, теперь действительно соответствует тому, что нам нужно, с помощью следующей альтернативы)
  • (?:\b(reduced|depressed|normal)\b\D*?)?\b(?:lv function|lv|systolic function|left ventricular ejection fraction)\b(?:\D*?\b(reduced|depressed|normal)\b)?:
    • (?:\b(reduced|depressed|normal)\b\D*?)? - необязательная группа без захвата, соответствующая reduced, depressed или normal , включенным в группу 1 (нам нужно извлечь слово, соответствующее с этой группой!) как целые слова, а затем любые 0+ не-ди git символов как можно меньше
    • \b(?:lv function|lv|systolic function|left ventricular ejection fraction)\b - любой из текстов внутри группы захвата как целые слова
    • (?:\D*?\b(reduced|depressed|normal)\b)? - необязательная группа без захвата, соответствующая как минимум 0 + non-di git символам, а затем включается в группу 2 a * 10 88 *, depressed или normal включены в Группу 1 как целое слово.

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

x <- c("lv function is reduced", "lv function is not reduced", "reduced lv function", "no evidence of reduced lv function")

cap <- "reduced|depressed|normal"
negate_prefix <- paste0("(?:\\b(?:no|not|none)\\b\\D*?\\b(?:",cap,")\\b\\D*?")
match <- "\\b(?:lv function|lv|systolic function|left ventricular ejection fraction)\\b"
regex <- paste0(negate_prefix,
   match, "|", match, "\\D*?\\bnot\\b\\D*?\\b(?:",cap,")\\b)(*SKIP)(*F)|(?:\\b(",cap,")\\b\\D*?)?",match,"(?:\\D*?\\b(",cap,")\\b)?")

Итак, все, что нам нужно, это захваченные подстроки . Смотрите Демоверсию R онлайн :

results <- regmatches(x, regexec(regex, x, perl=TRUE))
unlist(lapply(results, function(x) paste(x[-1], collapse="")))
## => [1] "reduced" ""        "reduced" "" 
0 голосов
/ 31 января 2020

если пример настолько сложный, насколько это возможно, то что-то подобное может сработать?

library(tidyverse)
library(stringr)
df <- data.frame(sent = c("lv function is reduced",
                             "lv function is not reduced",
                             "reduced lv function",
                             "no evidence of reduced lv function"))
df <- df %>% 
  mutate(out_test = +str_detect(sent, "not|no"),
         output = ifelse(out_test == 0, "reduced", NA)) %>% 
  select(-out_test)
df
                                sent  output
1             lv function is reduced reduced
2         lv function is not reduced    <NA>
3                reduced lv function reduced
4 no evidence of reduced lv function    <NA>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...