RegEx用于字符串中的条件模式

时间:2019-06-01 11:50:10

标签: r regex bioinformatics pcre regex-lookarounds

我需要从一些字符串中提取子字符串,例如: 我的数据是矢量:c("Shigella dysenteriae","PREDICTED: Ceratitis")

a = "Shigella dysenteriae"

b = "PREDICTED: Ceratitis"

我希望如果字符串以“ PREDICTED:”开头,则可以将其提取到后续单词(可能是“ Ceratitis”),并且如果字符串不是以“ PREDICTED”开头,则可以将其提取为第一个字(也许是志贺氏菌);

在此示例中,结果将是:

result_of_a = "Shigella"

result_of_b = "Ceratitis"

好吧,这是一个典型的条件正则表达式。我试过,但总是失败;

我使用了R,它可以兼容perl的正则表达式。

我知道R支持perl的正则表达式,因此我尝试使用regexprregmatches这两个函数来提取所需的子字符串。

代码是:


pattern = "(?<=PREDICTED:)?(?(1)(\\s+\\w+\\b)|(\\w+\\b))"

a = c("Shigella dysenteriae")
m_a = regexpr(pattern,a,perl = TRUE)
result_a = regmatches(a,m_a)

b = c("PREDICTED: Ceratitis")
m_b = regexpr(pattern,a,perl = TRUE)
result_b = regmatches(b,m_b)

最后,结果是:

# result_a = "Shigella"
# result_b = "PREDICTED"

这不是我期望的结果,result_a是正确的,result_b是错误的。

为什么?看来条件不起作用...

PS:    我试图阅读一些条件reg-expression的细节。这是我尝试阅读的网络:https://www.regular-expressions.info/conditional.html,我尝试从该网络模仿“模式”,还尝试使用“ RegexBuddy”软件查找原因。

3 个答案:

答案 0 :(得分:2)

我认为它不起作用的原因是因为(1) checks if a numbered capture group has been set,但是还没有设置第一个捕获组,也没有出现在(?<=PREDICTED:)?后面的正面。

接下来的部分中有一个第一和第二捕获组。 if子句将检查组1,未设置它,因此它将匹配组2。

如果将其设为唯一的捕获组(?<=(PREDICTED: )?)并省略其他2个,则if子句为true,但由于后向断言不是fixed length,您会收到错误消息。

除了使用条件模式,要获取两个单词,您可以使用捕获组并将PREDICTED:设为可选:

^(?:PREDICTED: )?(\w+)

Regex demo | R demo

答案 1 :(得分:1)

编辑: 要将以下函数用于矢量,可以执行以下操作: 向量:myvec<-c("Shigella dysenteriae","PREDICTED: Ceratitis")

lapply(myvec,extractor)
[[1]]
[1] "Shigella"

[[2]]
[1] "Ceratitis"

或者:

unlist(lapply(myvec,extractor))
[1] "Shigella"  "Ceratitis"

这假定字符串始终采用上面显示的格式:

extractor<- function(string){
if(grepl("^PREDICTED",string)){
  strsplit(string,": ")[[1]][2]
}
  else{
    strsplit(string," ")[[1]][1]
  }

}
 extractor(b)
 #[1] "Ceratitis"
 extractor(a)
 #[1] "Shigella"

答案 2 :(得分:0)

如果我理解正确,则OP要提取

  • “ PREDICTED:”之后的第一个单词(如果字符串以“ PREDICTED:”开头)
  • 如果字符串不是以“ PREDICTED:”开头,则
  • 字符串的第一个单词

因此,如果没有特定要求仅使用一个正则表达式,这就是我要做的:

  1. 删除所有开头的“ PREDICTED:”(如果有)
  2. 从中间结果中提取第一个单词。

对于使用正则表达式,我更喜欢使用Hadley Wickham的stringr软件包:

inp <- c("Shigella dysenteriae", "PREDICTED: Ceratitis")

library(magrittr) # piping used to improve readability
inp %>% 
  stringr::str_replace("^PREDICTED:\\s*", "") %>% 
  stringr::str_extract("^\\w+")
 [1] "Shigella"  "Ceratitis"

为了安全起见,我会事先删除所有前导空格:

inp %>% 
  stringr::str_trim() %>% 
  stringr::str_replace("^PREDICTED:\\s*", "") %>% 
  stringr::str_extract("^\\w+")