有人知道如何在表达式中找到第 n 次出现的字符串以及如何用正则表达式替换它吗?
例如我有以下字符串
txt <- "aaa-aaa-aaa-aaa-aaa-aaa-aaa-aaa-aaa-aaa"
我想用 '|' 替换第 5 次出现的 '-' 以及“||”第 7 次出现“-” 喜欢
[1] aaa-aaa-aaa-aaa-aaa|aaa-aaa||aaa-aaa-aaa
我该怎么做呢?
谢谢,弗洛里安
有人知道如何在表达式中找到第 n 次出现的字符串以及如何用正则表达式替换它吗?
例如我有以下字符串
txt <- "aaa-aaa-aaa-aaa-aaa-aaa-aaa-aaa-aaa-aaa"
我想用 '|' 替换第 5 次出现的 '-' 以及“||”第 7 次出现“-” 喜欢
[1] aaa-aaa-aaa-aaa-aaa|aaa-aaa||aaa-aaa-aaa
我该怎么做呢?
谢谢,弗洛里安
(1) sub它可以在单个正则表达式中完成sub
:
> sub("(^(.*?-){4}.*?)-(.*?-.*?)-", "\\1|\\3||", txt, perl = TRUE)
[1] "aaa-aaa-aaa-aaa-aaa|aaa-aaa||aaa-aaa-aaa"
(2) sub两次或调用两次的这种变体sub
:
> txt2 <- sub("(^(.*?-){6}.*?)-", "\\1|", txt, perl = TRUE)
> sub("(^(.*?-){4}.*?)-", "\\1||", txt2, perl = TRUE)
[1] "aaa-aaa-aaa-aaa-aaa|aaa-aaa||aaa-aaa-aaa"
(3) sub.fun或创建sub.fun
一种替代功能的这种变体。它利用gsubfn 包fn$
中的, , 和替换为参数。首先定义指定的函数,然后调用它两次。n-1
pat
value
sub
library(gsubfn)
sub.fun <- function(x, pat, n, value) {
fn$sub( "(^(.*?-){`n-1`}.*?)$pat", "\\1$value", x, perl = TRUE)
}
> sub.fun(sub.fun(txt, "-", 7, "||"), "-", 5, "|")
[1] "aaa-aaa-aaa-aaa-aaa|aaa-aaa||aaa-aaa-aaa"
(我们可以在using或给出基本 R 解决方案sub
的主体中修改参数,但代价是一些额外的冗长。)sub.fun
paste
sprintf
这可以重新表述为一个替换函数,给出这个令人愉悦的序列:
"sub.fun<-" <- sub.fun
tt <- txt # make a copy so that we preserve the input txt
sub.fun(tt, "-", 7) <- "||"
sub.fun(tt, "-", 5) <- "|"
> tt
[1] "aaa-aaa-aaa-aaa-aaa|aaa-aaa||aaa-aaa-aaa"
(4) gsubfn使用gsubfn
gsubfn包,我们可以使用一个特别简单的正则表达式(它只是"-"
),并且代码具有非常简单的结构。我们通过 proto 方法执行替换。包含该方法的 proto 对象被传递以代替替换字符串。这种方法的简单性源于gsubfn
自动使count
变量可用于此类方法的事实:
library(gsubfn) # gsubfn also pulls in proto
p <- proto(fun = function(this, x) {
if (count == 5) return("|")
if (count == 7) return("||")
x
})
> gsubfn("-", p, txt)
[1] "aaa-aaa-aaa-aaa-aaa|aaa-aaa||aaa-aaa-aaa"
更新:一些更正。
更新 2:为 (3) 添加了替换函数方法。
更新 3:pat
为sub.fun
.
另一种可能性是使用 Hadley 的stringr
包,它为我编写的函数奠定了基础:
require(stringr)
replace.nth <- function(string, pattern, replacement, n) {
locations <- str_locate_all(string, pattern)
str_sub(string, locations[[1]][n, 1], locations[[1]][n, 2]) <- replacement
string
}
txt <- "aaa-aaa-aaa-aaa-aaa-aaa-aaa-aaa-aaa-aaa"
txt.new <- replace.nth(txt, "-", "|", 5)
txt.new <- replace.nth(txt.new, "-", "||", 7)
txt.new
# [1] "aaa-aaa-aaa-aaa-aaa|aaa-aaa-aaa||aaa-aaa"
一种方法是使用gregexpr
查找 的位置-
:
posns <- gregexpr("-",txt)[[1]]
然后将相关的部分和分隔符粘贴在一起:
paste0(substr(txt,1,posns[5]-1),"|",substr(txt,posns[5]+1,posns[7]-1),"||",substr(txt,posns[7]+1,nchar(txt)))
[1] "aaa-aaa-aaa-aaa-aaa|aaa-aaa||aaa-aaa-aaa"