我正在尝试解析一个在每一行中都有文本的数据帧,并且在该文本中有我想隔离的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
)