stringr 删除第 n 次出现的字符
stringr remove n-th occurence of a character
我知道这个问题之前已经被问过和回答过(例如 or ),但出于某种原因我无法使用相应的正则表达式解决方案。
我基本上想从字符串中删除某个短语的第 n 次出现,特别是在示例中我想删除第二次出现的“ab”,但我的尝试都没有成功。
我有一个解决方法,使用 str_locate_all
,然后根据短语的位置执行 str_sub
,但我希望使用 str_remove
的简单正则表达式解决方案或 str_replace
如果我想用某些东西替换这第二次出现。
text <- "abcdabef"
预期输出:
"abcdef"
我尝试过的无效解决方案(以及许多其他解决方案):
library(stringr)
str_remove_all(y, "(?:ab){2}")
str_remove_all(y, "(?:ab){1}.*(ab)")
要仅删除第二次出现,您需要使用
sub("(ab.*?)ab", "\1", "abcdabef")
要删除第 n 次出现,请在组后使用限制量词,其中唯一的 min
值应等于 n-1
:
n <- 2
sub(paste0("((?:ab.*?){",n-1,"})ab"), "\1", "abcdabef", perl=TRUE)
注:
您需要使用 sub
而不是 gsub
,因为您只需要完成一次替换。
图案详情(当n=3
):
((?:ab.*?){2})
- 第 1 组 (</code>):出现两次 <code>ab
和除换行字符以外的任何零个或多个字符(因为我使用的是 perl=TRUE
这里,如果需要多行匹配支持,在开头加上(?s)
或者把.*?
换成(?s:.*?)
)尽量少
ab
- 一个 ab
如果你有带有特殊字符的任意字符串,你需要转义它们:
regex.escape <- function(string) {
gsub("([][{}()+*^$|\\?.])", "\\\1", string)
}
word <- "a+(b)"
word <- regex.escape(word)
text <- "a+(b)1___a+(b)2___a+(b)3___a+(b)4"
n <- 3 # Let's remove the 3rd occurrence of a+(b)
sub(paste0("((?:", word, ".*?){",n-1,"})", word), "\1", text, perl=TRUE)
## => [1] "a+(b)1___a+(b)2___3___a+(b)4"
参见regex demo。
另一种可能的解决方案,使用 stringr
而不使用 regex
(它也适用于任何 n
):
library(tidyverse)
text <- "abcdabef"
n <- 2
str_locate_all(text, "ab") %>% .[[1]] %>%
when(n <= nrow(.) ~ `str_sub<-`(text, .[n, 1], .[n, 2], value = ""), ~ text)
#> [1] "abcdef"
我知道这个问题之前已经被问过和回答过(例如
我基本上想从字符串中删除某个短语的第 n 次出现,特别是在示例中我想删除第二次出现的“ab”,但我的尝试都没有成功。
我有一个解决方法,使用 str_locate_all
,然后根据短语的位置执行 str_sub
,但我希望使用 str_remove
的简单正则表达式解决方案或 str_replace
如果我想用某些东西替换这第二次出现。
text <- "abcdabef"
预期输出:
"abcdef"
我尝试过的无效解决方案(以及许多其他解决方案):
library(stringr)
str_remove_all(y, "(?:ab){2}")
str_remove_all(y, "(?:ab){1}.*(ab)")
要仅删除第二次出现,您需要使用
sub("(ab.*?)ab", "\1", "abcdabef")
要删除第 n 次出现,请在组后使用限制量词,其中唯一的 min
值应等于 n-1
:
n <- 2
sub(paste0("((?:ab.*?){",n-1,"})ab"), "\1", "abcdabef", perl=TRUE)
注:
您需要使用 sub
而不是 gsub
,因为您只需要完成一次替换。
图案详情(当n=3
):
((?:ab.*?){2})
- 第 1 组 (</code>):出现两次 <code>ab
和除换行字符以外的任何零个或多个字符(因为我使用的是perl=TRUE
这里,如果需要多行匹配支持,在开头加上(?s)
或者把.*?
换成(?s:.*?)
)尽量少ab
- 一个ab
如果你有带有特殊字符的任意字符串,你需要转义它们:
regex.escape <- function(string) {
gsub("([][{}()+*^$|\\?.])", "\\\1", string)
}
word <- "a+(b)"
word <- regex.escape(word)
text <- "a+(b)1___a+(b)2___a+(b)3___a+(b)4"
n <- 3 # Let's remove the 3rd occurrence of a+(b)
sub(paste0("((?:", word, ".*?){",n-1,"})", word), "\1", text, perl=TRUE)
## => [1] "a+(b)1___a+(b)2___3___a+(b)4"
参见regex demo。
另一种可能的解决方案,使用 stringr
而不使用 regex
(它也适用于任何 n
):
library(tidyverse)
text <- "abcdabef"
n <- 2
str_locate_all(text, "ab") %>% .[[1]] %>%
when(n <= nrow(.) ~ `str_sub<-`(text, .[n, 1], .[n, 2], value = ""), ~ text)
#> [1] "abcdef"