正则表达式解决方案将非常复杂,只有在您理解它的情况下才能使用它。我会尽量解释清楚。
问:如果我的lookbehinds 不支持这样的模式,我如何匹配前面没有未知长度字符串的内容?
A :匹配你不需要的,跳过匹配的文本,从匹配失败的位置继续匹配。
您可以使用支持(*SKIP)(*FAIL)(或更短的(*SKIP)(*F))构造的PCRE 正则表达式来实现。
现在,看看模式:
(?:\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)?
看起来很笨拙,但让我们来看看成分:
-
(?: - 作为容器的非捕获组的开始,(*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+ 个非数字字符
-
\b(?:reduced|depressed|normal)\b - 非捕获组内的任何单词作为整个单词
-
\D*? - 0+ 个非数字字符
-
\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 - 非捕获组内的任何文本作为整个单词
-
\D*?\bnot\b\D*? - 0+ 非数字尽可能少,整个单词 not,0+ 非数字尽可能少
-
\b(?:reduced|depressed|normal)\b - 非捕获组内的任何文本作为整个单词
-
)(*SKIP)(*F) - 容器组的结尾,以及匹配失败的 PCRE 动词,使正则表达式引擎继续从匹配失败的位置开始搜索匹配
-
| - 或者(也就是说,现在,与我们需要的下一个替代方案真正匹配)
-
(?:\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+ 非数字字符
-
\b(?:lv function|lv|systolic function|left ventricular ejection fraction)\b - 非捕获组内的任何文本作为整个单词
-
(?:\D*?\b(reduced|depressed|normal)\b)? - 一个可选的非捕获组,尽可能少地匹配任何 0+ 个非数字字符,然后捕获到第 2 组 a reduced、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)?")
所以,我们只需要捕获的子字符串。见the R demo online:
results <- regmatches(x, regexec(regex, x, perl=TRUE))
unlist(lapply(results, function(x) paste(x[-1], collapse="")))
## => [1] "reduced" "" "reduced" ""