通过正则表达式根据字符串中的位置替换子字符串

tho*_*hal 5 regex r stringr

假设我的字符串中有一个特定的模式,该模式出现了已知的次数 ( n),并且我们不想对字符串的其余部分(特别是这些模式之间的字符串)做出任何假设。

此外,我有一个长度向量nsf例如),我想用相应的元素修改模式的每次出现。因此,对于每场比赛,我想知道比赛已经发生了多少次?

我可以想到以下解决方案:

library(stringr)
sf <- letters[4:1]
ss <- "fdskjhf xx sd ss xx wwwe xx ss  xx sdsd"
#              ^^ 1st   ^^ 2nd  ^^ 3rd ^^ 4th
# add:         _sf[1]   _sf[2]  _sf[3] _sf[4]
# that is:     xx_d     xx_c    xx_b   xx_a


## add _sf[i] to the ith occurence of "xx" in ss
goal <- "fdskjhf xx_d sd ss xx_c wwwe xx_b ss  xx_a sdsd"

my_replacer_factory <- function(sf, start = 0) {
  cnt <- start
  function(el) {
    cnt <<- cnt + 1
    paste0(el, "_", rev(sf)[cnt])
  }
}

my_replacer <- my_replacer_factory(sf)
(res <- str_replace_all(ss, fixed("xx"), my_replacer))
# [1] "fdskjhf xx_d sd ss xx_c wwwe xx_b ss  xx_a sdsd"

all.equal(res, goal)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)

str_replace_all这显然有效,但感觉容易出错,因为我依赖于从右侧开始替换的事实。如果在未来的实现中这种行为发生变化或变得并行化怎么办?

知道如何以不同的方式实现这一目标吗?理想情况下使用 stringr 函数吗?


类似的想法:

library(stringr)
sf <- letters[4:1]
ss <- "fdskjhf xx sd ss xx wwwe xx ss  xx sdsd"
#              ^^ 1st   ^^ 2nd  ^^ 3rd ^^ 4th
# add:         _sf[1]   _sf[2]  _sf[3] _sf[4]
# that is:     xx_d     xx_c    xx_b   xx_a


## add _sf[i] to the ith occurence of "xx" in ss
goal <- "fdskjhf xx_d sd ss xx_c wwwe xx_b ss  xx_a sdsd"

my_replacer_factory <- function(sf, start = 0) {
  cnt <- start
  function(el) {
    cnt <<- cnt + 1
    paste0(el, "_", rev(sf)[cnt])
  }
}

my_replacer <- my_replacer_factory(sf)
(res <- str_replace_all(ss, fixed("xx"), my_replacer))
# [1] "fdskjhf xx_d sd ss xx_c wwwe xx_b ss  xx_a sdsd"

all.equal(res, goal)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)

GKi*_*GKi 5

一种方法是使用regmatches<-.

sf <- letters[4:1]
ss <- "fdskjhf xx sd ss xx wwwe xx ss  xx sdsd"

regmatches(ss, gregexpr("xx", ss)) <- list(paste0("xx_", sf))
ss
#[1] "fdskjhf xx_d sd ss xx_c wwwe xx_b ss  xx_a sdsd"

#Alternative with look behind
regmatches(ss, gregexpr("(?<=xx)", ss, perl=TRUE)) <- list(paste0("_", sf))
Run Code Online (Sandbox Code Playgroud)