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)?")
#cat(regex, collapse="\n") # => (?:\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)?
results <- regmatches(x, regexec(regex, x, perl=TRUE))
unlist(lapply(results, function(x) paste(x[-1], collapse="")))
eCA8LSBjKCJsdiBmdW5jdGlvbiBpcyByZWR1Y2VkIiwgImx2IGZ1bmN0aW9uIGlzIG5vdCByZWR1Y2VkIiwgInJlZHVjZWQgbHYgZnVuY3Rpb24iLCAibm8gZXZpZGVuY2Ugb2YgcmVkdWNlZCBsdiBmdW5jdGlvbiIpCgpjYXAgPC0gInJlZHVjZWR8ZGVwcmVzc2VkfG5vcm1hbCIKbmVnYXRlX3ByZWZpeCA8LSBwYXN0ZTAoIig/OlxcYig/Om5vfG5vdHxub25lKVxcYlxcRCo/XFxiKD86IixjYXAsIilcXGJcXEQqPyIpCm1hdGNoIDwtICJcXGIoPzpsdiBmdW5jdGlvbnxsdnxzeXN0b2xpYyBmdW5jdGlvbnxsZWZ0IHZlbnRyaWN1bGFyIGVqZWN0aW9uIGZyYWN0aW9uKVxcYiIKcmVnZXggPC0gcGFzdGUwKG5lZ2F0ZV9wcmVmaXgsCiAgIG1hdGNoLCAifCIsIG1hdGNoLCAiXFxEKj9cXGJub3RcXGJcXEQqP1xcYig/OiIsY2FwLCIpXFxiKSgqU0tJUCkoKkYpfCg/OlxcYigiLGNhcCwiKVxcYlxcRCo/KT8iLG1hdGNoLCIoPzpcXEQqP1xcYigiLGNhcCwiKVxcYik/IikKI2NhdChyZWdleCwgY29sbGFwc2U9IlxuIikgIyA9PiAoPzpcYig/Om5vfG5vdHxub25lKVxiXEQqP1xiKD86cmVkdWNlZHxkZXByZXNzZWR8bm9ybWFsKVxiXEQqP1xiKD86bHYgZnVuY3Rpb258bHZ8c3lzdG9saWMgZnVuY3Rpb258bGVmdCB2ZW50cmljdWxhciBlamVjdGlvbiBmcmFjdGlvbilcYnxcYig/Omx2IGZ1bmN0aW9ufGx2fHN5c3RvbGljIGZ1bmN0aW9ufGxlZnQgdmVudHJpY3VsYXIgZWplY3Rpb24gZnJhY3Rpb24pXGJcRCo/XGJub3RcYlxEKj9cYig/OnJlZHVjZWR8ZGVwcmVzc2VkfG5vcm1hbClcYikoKlNLSVApKCpGKXwoPzpcYihyZWR1Y2VkfGRlcHJlc3NlZHxub3JtYWwpXGJcRCo/KT9cYig/Omx2IGZ1bmN0aW9ufGx2fHN5c3RvbGljIGZ1bmN0aW9ufGxlZnQgdmVudHJpY3VsYXIgZWplY3Rpb24gZnJhY3Rpb24pXGIoPzpcRCo/XGIocmVkdWNlZHxkZXByZXNzZWR8bm9ybWFsKVxiKT8KcmVzdWx0cyA8LSByZWdtYXRjaGVzKHgsIHJlZ2V4ZWMocmVnZXgsIHgsIHBlcmw9VFJVRSkpCnVubGlzdChsYXBwbHkocmVzdWx0cywgZnVuY3Rpb24oeCkgcGFzdGUoeFstMV0sIGNvbGxhcHNlPSIiKSkp