在 R 中向前看以按顺序识别单词模式

lookahead in R to identify a pattern of words in order

我正在尝试解析一组字符串。 我需要查明样本中是否检测到 'bcl-2'。 例如:"bl-2 was detected in 45% of patients"。 然而,某些可能的变化具有挑战性:

1."bcl-2 was detected in 45% bcl-6 was not detected"
2."bcl-2 was not detected bcl-6 was detected in 45%"
3.“没有 bcl-2 bcl-6 的证据在 45% 中被检测到”

所以我正在尝试定义正则表达式代码:

1. 展望 'bcl-2'
2. 然后,从那个点向前看 'detected'
3、然后在'bcl-2'和'detected'之间看后面,确定没有'not'.
4.如果可能的话看后面'bcl-2'确保有'no evidence of'(虽然我可以单独处理这个条件)

我尝试了以下无效的代码。具体来说,它不会向后看,所以我猜想我缺少一些内在的向后看的东西。

此正则表达式适用于 "bcl-2 was not detected" 但不适用于 "bcl-2 was detected in 45% bcl-6 was not detected"

y="bcl-2 was detected in 45% bcl-6 was not detected"
grepl("(?=bcl-?2)(?!.*not)(?=.*detected)",y, ignore.case = T,perl=T)  

所以我认为这行得通,但行不通:

grepl("(?=bcl-?2)(?=.*detected)(?<!not)",y, ignore.case = T,perl=T)

我正在尝试理解lookbehind 的逻辑。关于最后一行代码 -> 我认为 (?=bcl-?2) 向前看,直到字符串中以 'bcl-2' 开头的点。然后,我认为 (?=.*detected) 向前看,直到字符串中 'detected' 开始的位置。然后我认为 lookbehind 开始从那个位置向后看 'not'。这当然是错误的......所以我对环视逻辑缺少什么

顺便说一句,我一直在使用一个很棒的网站来解决这个问题 https://www.regular-expressions.info/recurse.html

环视是零宽度断言,这意味着正则表达式索引在匹配模式时不会移动(匹配的字符不会添加到匹配值中,并且连续的环视都从相同的位置开始它们的模式检查)。因此,(?=bcl-?2)(?!.*not)(?=.*detected) 匹配后跟 bcl2bcl-2 的空位置(空字符串),在除换行符以外的任何 0+ 个字符之后没有 not 子字符串,然后是 detected 在除换行符之外的任何 0+ 个字符之后。在输入字符串中的每个位置都尝试使用此模式,因为没有锚点。该模式几乎无法满足您的需求。

这是一个可能的解决方案:

\bbcl-2\b(?:(?!\bbcl-\d|\bnot\b).)*?\bdetected\b

regex demo:

  • \b - 单词边界
  • bcl-2 - bcl-2 子串
  • \b - 单词边界
  • (?:(?!\bbcl-\d|\bnot\b).)*? - (a ) 任何 0+(但尽可能少)字符,而不是不开始以下两个序列的换行字符:
    • \bbcl-\d - 工作边界后跟 bcl- 和数字
    • | - 或
    • \bnot\b - 一个完整的单词 not
  • \bdetected\b - 一个完整的单词 detected

请参阅下面的 R demo

x <- c("bcl-2 was detected in 45% bcl-6 was not detected", 
"bcl-2 was not detected bcl-6 was detected in 45%",
"no evidendce of bcl-2 bcl-6 was detected in 45%")
grep("\bbcl-2\b(?:(?!\bbcl-\d|\bnot\b).)*?\bdetected\b", x, perl=TRUE, value=TRUE)
## => [1] "bcl-2 was detected in 45% bcl-6 was not detected"