grep
、grepl
、regexpr
、gregexpr
、sub
或gsub
都不返回分组捕获。我需要从编码为键值对的字符串中提取键值对。
\((.*?) :: (0\.[0-9]+)\)
我总是可以使用多个完全匹配的grep,或进行一些非R处理,但我希望可以在R内完成所有操作。是否有函数或包提供此类功能以实现此目的?
grep
、grepl
、regexpr
、gregexpr
、sub
或gsub
都不返回分组捕获。\((.*?) :: (0\.[0-9]+)\)
我总是可以使用多个完全匹配的grep,或进行一些非R处理,但我希望可以在R内完成所有操作。是否有函数或包提供此类功能以实现此目的?
str_match()
函数来自于stringr
包,可以实现此功能。它返回一个字符矩阵,其中每个匹配组对应一列(还有一个列对应整个匹配):
> s = c("(sometext :: 0.1231313213)", "(moretext :: 0.111222)")
> str_match(s, "\\((.*?) :: (0\\.[0-9]+)\\)")
[,1] [,2] [,3]
[1,] "(sometext :: 0.1231313213)" "sometext" "0.1231313213"
[2,] "(moretext :: 0.111222)" "moretext" "0.111222"
从你的例子中,gsub可以实现这个功能:
gsub("\\((.*?) :: (0\\.[0-9]+)\\)","\\1 \\2", "(sometext :: 0.1231313213)")
[1] "sometext 0.1231313213"
你需要在引号中双重转义 \s,然后它们才能在正则表达式中起作用。
希望这可以帮到你。
gsub
的手册非常需要一个例子,显示您需要使用 '\1' 转义捕获组引用。 - smci尝试使用regmatches()
和regexec()
:
regmatches("(sometext :: 0.1231313213)",regexec("\\((.*?) :: (0\\.[0-9]+)\\)","(sometext :: 0.1231313213)"))
[[1]]
[1] "(sometext :: 0.1231313213)" "sometext" "0.1231313213"
regexec
返回一个列表,其中包含有关匹配位置的信息,因此 regmatches
要求用户提供匹配列表所属的字符串。 - RTbecardgsub()函数可以做到这一点,并且只返回捕获组:
然而,为了使其工作,您必须像在 gsub() 帮助中提到的那样显式选择捕获组之外的元素。
字符向量 'x' 的(...)元素不会被替换,并将原样返回。
因此,如果要选择的文本位于某个字符串的中间,在捕获组之前和之后添加 .* 应该允许您仅返回它。
gsub(".*\\((.*?) :: (0\\.[0-9]+)\\).*","\\1 \\2", "(sometext :: 0.1231313213)")
[1] "sometext 0.1231313213"
使用utils
中的strcapture
解决方案:
x <- c("key1 :: 0.01",
"key2 :: 0.02")
strcapture(pattern = "(.*) :: (0\\.[0-9]+)",
x = x,
proto = list(key = character(), value = double()))
#> key value
#> 1 key1 0.01
#> 2 key2 0.02
我喜欢Perl兼容的正则表达式,可能其他人也一样...
这里有一个函数,它可以实现Perl兼容的正则表达式,并且与我习惯使用的其他语言中的函数具有相同的功能:
regexpr_perl <- function(expr, str) {
match <- regexpr(expr, str, perl=T)
matches <- character(0)
if (attr(match, 'match.length') >= 0) {
capture_start <- attr(match, 'capture.start')
capture_length <- attr(match, 'capture.length')
total_matches <- 1 + length(capture_start)
matches <- character(total_matches)
matches[1] <- substr(str, match, match + attr(match, 'match.length') - 1)
if (length(capture_start) > 1) {
for (i in 1:length(capture_start)) {
matches[i + 1] <- substr(str, capture_start[[i]], capture_start[[i]] + capture_length[[i]] - 1)
}
}
}
matches
}
gregexpr
调用,然后提取出匹配的子字符串:regex.string <- "(?<=\\().*?(?= :: )"
regex.number <- "(?<= :: )\\d\\.\\d+"
match.string <- gregexpr(regex.string, str, perl=T)[[1]]
match.number <- gregexpr(regex.number, str, perl=T)[[1]]
strings <- mapply(function (start, len) substr(str, start, start+len-1),
match.string,
attr(match.string, "match.length"))
numbers <- mapply(function (start, len) as.numeric(substr(str, start, start+len-1)),
match.number,
attr(match.number, "match.length"))
expr "xyx0.0023xyxy" : '[^0-9]*\([.0-9]\+\)'
。 - Aleksandr Levchuk如同 stringr
包中所建议的,可以使用 str_match()
或 str_extract()
来实现此功能。
来自手册的改编:
library(stringr)
strings <- c(" 219 733 8965", "329-293-8753 ", "banana",
"239 923 8115 and 842 566 4692",
"Work: 579-499-7527", "$1000",
"Home: 543.355.3679")
phone <- "([2-9][0-9]{2})[- .]([0-9]{3})[- .]([0-9]{4})"
提取和组合我们的群组:
str_extract_all(strings, phone, simplify=T)
# [,1] [,2]
# [1,] "219 733 8965" ""
# [2,] "329-293-8753" ""
# [3,] "" ""
# [4,] "239 923 8115" "842 566 4692"
# [5,] "579-499-7527" ""
# [6,] "" ""
# [7,] "543.355.3679" ""
使用输出矩阵指示组(我们只关心第二列及之后的列):
str_match_all(strings, phone)
# [[1]]
# [,1] [,2] [,3] [,4]
# [1,] "219 733 8965" "219" "733" "8965"
#
# [[2]]
# [,1] [,2] [,3] [,4]
# [1,] "329-293-8753" "329" "293" "8753"
#
# [[3]]
# [,1] [,2] [,3] [,4]
#
# [[4]]
# [,1] [,2] [,3] [,4]
# [1,] "239 923 8115" "239" "923" "8115"
# [2,] "842 566 4692" "842" "566" "4692"
#
# [[5]]
# [,1] [,2] [,3] [,4]
# [1,] "579-499-7527" "579" "499" "7527"
#
# [[6]]
# [,1] [,2] [,3] [,4]
#
# [[7]]
# [,1] [,2] [,3] [,4]
# [1,] "543.355.3679" "543" "355" "3679"
_all
后缀来纠正相关的 stringr
函数。 - Megatron# install.packages("unglue")
library(unglue)
s <- c("(sometext :: 0.1231313213)", "(moretext :: 0.111222)")
unglue_data(s, "({x} :: {y})")
#> x y
#> 1 sometext 0.1231313213
#> 2 moretext 0.111222
df <- data.frame(col = s)
unglue_unnest(df, col, "({x} :: {y})",remove = FALSE)
#> col x y
#> 1 (sometext :: 0.1231313213) sometext 0.1231313213
#> 2 (moretext :: 0.111222) moretext 0.111222
unglue_regex("({x} :: {y})")
#> ({x} :: {y})
#> "^\\((.*?) :: (.*?)\\)$"
unglue_regex("({x} :: {y})",named_capture = TRUE)
#> ({x} :: {y})
#> "^\\((?<x>.*?) :: (?<y>.*?)\\)$"
更多信息: https://github.com/moodymudskipper/unglue/blob/master/README.md
str_match_all()
函数来匹配正则表达式中的所有组。 - smci[,1]
是完整匹配。[,2:3]
是捕获的组。 - Kent Johnson