我正在尝试解析一个在每一行中都有文本的数据帧,并且在该文本中有我想隔离的IP地址。但是,我仍然选择整数,整数和句点。以下是我正在使用的示例。

    z <- data.frame( x =  c('112.68.196.98   5.32', '192.41.196.888', '..','5.32  88'))
    gsub("^\\.+|\\.[^.]*$", "", z$x, perl=TRUE)

我正在寻找清理此数据框,以便输出将是:
    z <- data.frame( x =  c('112.68.196.98', '192.41.196.888','',''))

我似乎无法提出适当的正则表达式放入gsub中。谢谢。

最佳答案

我认为这应该工作:

re <- regexpr(
  "(?(?=.*?(\\d+\\.\\d+\\.\\d+\\.\\d+).*?)(\\1|))",
  z$x, perl = TRUE)

regmatches(z$x, re)
#[1] "112.68.196.98"  "192.41.196.888" ""               ""

这使用正则表达式为条件,在\\1上存在正匹配的情况下保留捕获组(.*?(\\d+\\.\\d+\\.\\d+\\.\\d+).*?),否则返回空结果。

更新:

关于您的评论,我认为以下更改将使您可以在单个字符串中捕获多个IP地址。首先,从regexpr切换到gregexpr以允许多个结果:
re2 <- gregexpr(
  "(?(?=.*?(\\d+\\.\\d+\\.\\d+\\.\\d+).*?)(\\1|))",
  z2$x, perl = TRUE
)

由于在regmatches输入上调用gregexpr将返回一个列表,因此需要进行一些其他处理:
res2 <- sapply(regmatches(z2$x, re2), function(x) {
  gsub(
    "^\\s+|\\s+$", "",
    gsub("\\s+", " ", paste0(x, collapse = " "))
  )
}

例如,这应该适合与data.frame重新组合为新列:
res2
#[1] "112.68.196.98 192.41.196.888" "192.41.196.888"
#     ""                             "112.68.196.98"

而且,如果您确实想将每个结果分成自己的字符串,则表达式会更简单一些(与sapply(...)相比):
lapply(regmatches(z2$x, re2), function(x) {
  Filter(function(y) y != "", x)
})
#[[1]]
#[1] "112.68.196.98"  "192.41.196.888"

#[[2]]
#[1] "192.41.196.888"

#[[3]]
#character(0)

#[[4]]
#[1] "112.68.196.98"

数据:
z2 <- data.frame(
  x = c('112.68.196.98 5.32 192.41.196.888',
        '192.41.196.888',
        '..', '5.32 88 112.68.196.98'),
  stringsAsFactors = FALSE
)

10-06 06:37