Решение 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" ""