【问题标题】:RegEx for a conditional pattern in a string字符串中条件模式的正则表达式
【发布时间】:2019-10-17 18:35:44
【问题描述】:

我需要从一些字符串中提取子字符串,例如: 我的数据是一个向量: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是错的。

WHY???看来条件不行……

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

【问题讨论】:

  • 它们是在某种列表、数据框中还是只是独立存储?
  • 向量,就像c("痢疾志贺氏菌","PREDICTED: Ceratitis")

标签: r regex pcre regex-lookarounds


【解决方案1】:

我认为它不起作用的原因是因为(1)checks if a numbered capture group has been set 但是还没有第一个捕获组集,也没有在(?&lt;=PREDICTED:)? 的积极后视中。

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

如果您将其设为唯一的捕获组 (?&lt;=(PREDICTED: )?) 并省略其他 2 个,则 if 子句将为真,但您将收到错误,因为后向断言不是 fixed length

您可以使用捕获组并将PREDICTED: 设为可选,而不是使用条件模式来获取这两个词:

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

Regex demo | R demo

【讨论】:

    【解决方案2】:

    编辑: 要在向量上使用以下函数,可以执行以下操作: 向量:myvec&lt;-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"
    

    【讨论】:

      【解决方案3】:

      如果我理解正确,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+")
      

      【讨论】:

      • 非常感谢,这个答案通俗易懂
      猜你喜欢
      • 2015-11-28
      • 1970-01-01
      • 2019-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多