我是R的新手,我坚持使用似乎无法正常工作的反向引用。在:
gsub("\\((\\d+)\\)", f("\\1"), string)
它正确地抓住了括号之间的数字但是没有应用(正确定义的,否则正常工作)函数f来替换数字 - >它实际上是字符串" \ 1"传递给f。
我错过了什么或只是R不处理这个?如果是这样,任何想法我怎么能做类似的事情,即在飞行中应用一个功能"在我正在解析的文本中括号之间出现的(实际上很多)数字?
非常感谢你的帮助。
答案 0 :(得分:5)
R无法通过gsub
直接将匹配功能应用于匹配项。您实际上必须提取匹配,转换值,然后替换值。使用regmatches
函数可以轻松实现这一点。例如
x<-"(990283)M (31)O (29)M (6360)M"
f<-function(x) {
v<-as.numeric(substr(x,2,nchar(x)-1))
paste0(v+5,".1")
}
m <- gregexpr("\\(\\d+\\)", x)
regmatches(x, m) <- lapply(regmatches(x, m), f)
x
# [1] "990288.1M 36.1O 34.1M 6365.1M"
当然,您可以f
做任何您喜欢的事情,只要确保它对矢量友好。当然,你可以将它包装在你自己的函数中
gsubf <- function(pattern, x, f) {
m <- gregexpr(pattern, x)
regmatches(x, m) <- lapply(regmatches(x, m), f)
x
}
gsubf("\\(\\d+\\)", x, f)
请注意,在这些示例中我们不使用捕获组,我们只是抓住整个匹配。有一些方法可以提取捕获组,但它们有点混乱。如果你想提供一个需要这种提取的例子,我可能会想出更高级的东西。
答案 1 :(得分:1)
要在具有正则表达式的替换功能中使用回调,可以使用gsubfn
或stringr
函数。
在它们之间进行选择时,请注意stringr
基于ICU正则表达式引擎,并且与gsubfn
一起使用,您可以使用默认的 TCL (如果R安装具有{ {1}}功能,否则为默认TRE)或PCRE(如果传递了tcltk
参数)。
还要注意,perl=TRUE
允许访问匹配对象中的所有捕获组,而gsubfn
仅允许操纵整个匹配项。因此,对于str_replace_all
,正则表达式应类似于str_replace_all
,其中仅当1+个数字用(?<=\()\d+(?=\))
和(
括起来时才被匹配,< / p>
对于)
,您可以使用stringr
:
str_replace_all
通过library(stringr)
string <- "(990283)M (31)O (29)M (6360)M"
## Callback function to increment found number:
f <- function(x) { as.integer(x) + 1 }
str_replace_all(string, "(?<=\\()\\d+(?=\\))", function(m) f(m))
## => [1] "(990284)M (32)O (30)M (6361)M"
,传递gsubfn
和perl=TRUE
可以使用环顾四周,并且只需修改整个匹配项即可:
backref=0
如果模式中有多个组,请删除gsubfn("(?<=\\()\\d+(?=\\))", ~ f(m), string, perl=TRUE, backref=0)
## => [1] "(990284)M (32)O (30)M (6361)M"
并在回调函数声明中枚举组值参数:
backref=0
答案 2 :(得分:0)
这适用于多种不同的替代品。
text="foo(200) (300)bar (400)foo (500)bar (600)foo (700)bar"
f=function(x)
{
return(as.numeric(x[[1]])+5)
}
a=strsplit(text,"\\(\\K\\d+",perl=T)[[1]]
b=f(str_extract_all(text,perl("\\(\\K\\d+")))
paste0(paste0(a[-length(a)],b,collapse=""),a[length(a)]) #final output
#[1] "foo(205) (305)bar (405)foo (505)bar (605)foo (705)bar"
答案 3 :(得分:0)
这是一种通过在替换参数中稍微调整stringr::str_replace()
的方式,只需使用lambda公式作为替换参数,然后不使用""\\1"
而是使用..1
引用捕获的组,因此您的gsub("\\((\\d+)\\)", f("\\1"), string)
将变成str_replace2(string, "\\((\\d+)\\)", ~f(..1))
,或者在这种简单情况下变成str_replace2(string, "\\((\\d+)\\)", f)
:
str_replace2 <- function(string, pattern, replacement, type.convert = TRUE){
if(inherits(replacement, "formula"))
replacement <- rlang::as_function(replacement)
if(is.function(replacement)){
grps_mat <- stringr::str_match(string, pattern)[,-1, drop = FALSE]
grps_list <- lapply(seq_len(ncol(grps_mat)), function(i) grps_mat[,i])
if(type.convert) {
grps_list <- type.convert(grps_list, as.is = TRUE)
replacement <- rlang::exec(replacement, !!! grps_list)
replacement <- as.character(replacement)
} else {
replacement <- rlang::exec(replacement, !!! grps_list)
}
}
stringr::str_replace(string, pattern, replacement)
}
str_replace2(
"foo (4)",
"\\((\\d+)\\)",
sqrt)
#> [1] "foo 2"
str_replace2(
"foo (4) (5)",
"\\((\\d+)\\) \\((\\d+)\\)",
~ sprintf("(%s)", ..1 * ..2))
#> [1] "foo (20)"
由reprex package(v0.3.0)于2020-01-24创建