如何提取匹配模式后出现的第一个数字

时间:2017-07-27 23:07:56

标签: r regex

请考虑以下示例:

examples <- c(
  "abc foo",
  "abc foo 17",
  "0 abc defg foo 5 121",
  "abc 12 foo defg 11"
)

这里我想返回“foo”之后出现的第一个数字。在这种情况下:NA,17,5,11。我该怎么做?我尝试使用后视,但没有运气。

library(stringr)
str_extract(examples, "(?<=foo.*)[0-9]+")

Error in stri_extract_first_regex(string, pattern, opts_regex = opts(pattern)) : 
  Look-Behind pattern matches must have a bounded maximum length. (U_REGEX_LOOK_BEHIND_LIMIT)

3 个答案:

答案 0 :(得分:5)

这似乎有效:

str_match(examples, "foo.*?(\\d+)")

     [,1]          [,2]
[1,] NA            NA  
[2,] "foo 17"      "17"
[3,] "foo 5"       "5" 
[4,] "foo defg 11" "11"

来自?regex

  

默认情况下,重复是贪婪的,因此使用最大可能的重复次数。通过将?附加到量词,可以将其更改为“minimal”。

来自?str_extract

  

另见

     

?str_match提取匹配的组; ?stri_extract用于底层实现。

答案 1 :(得分:1)

您可以使用base R solution like this

> res <- gsub(".*?foo\\D*(\\d+).*|.*", "\\1", examples)
> res[nchar(res)==0] <- NA
> res
[1] NA   "17" "5"  "11"

由于正则表达式将始终匹配任何字符串,因此您无需再运行两次正则表达式替换,只需使用NA填充空值作为第二步。

模式匹配:

  • .*?foo - 任意0个字符尽可能少(因为*?是懒惰的)直到第一次出现foo然后foo本身
  • \\D* - 零个或多个非数字字符
  • (\\d+) - 捕获1个或多个数字的组1(之后,存储在组中的值可以通过\1反向引用引用)
  • .* - 字符串的其余部分
  • | - 或
  • .* - 即使是空的整个字符串。

答案 2 :(得分:0)

基础R gsub可以做到:

# pulls fist instance of a digit 
gsub('^\\D*(\\d*).*', '\\1', examples)
[1] ""   "17" "0"  "12"

编辑:使用基础R的实际解决方案

ifelse(
     grepl('foo\\D*\\d', examples), 
     gsub('^\\D*(\\d+).*', '\\1', gsub('.*foo\\s*', '', examples)), 
     NA)
[1] NA   "17" "5"  "11"