For the first and last, we can use stri_replace
from stringi
as it has the option
library(stringi)
stri_replace(mystring, fixed="fish", "dog", mode="first")
#[1] "one dog two fish red fish blue fish"
stri_replace(mystring, fixed="fish", "dog", mode="last")
#[1] "one fish two fish red fish blue dog"
The mode
can only have values 'first', 'last' and 'all'. So, other options are not in the default function. We may have to use regex
option to change it.
Using sub
, we can do the nth replacement of word
sub("^((?:(?!fish).)*fish(?:(?!fish).)*)fish",
"\\1dog", mystring, perl=TRUE)
#[1] "one fish two dog red fish blue fish"
Or we can use
sub('^((.*?fish.*?){2})fish', "\\1\\dog", mystring, perl=TRUE)
#[1] "one fish two fish red dog blue fish"
Just for easiness, we can create a function to do this
patfn <- function(n){
stopifnot(n>1)
sprintf("^((.*?\\bfish\\b.*?){%d})\\bfish\\b", n-1)
}
and replace the nth occurrence of 'fish' except the first one which can be easily done using sub
or the default option in str_replace
sub(patfn(2), "\\1dog", mystring, perl=TRUE)
#[1] "one fish two dog red fish blue fish"
sub(patfn(3), "\\1dog", mystring, perl=TRUE)
#[1] "one fish two fish red dog blue fish"
sub(patfn(4), "\\1dog", mystring, perl=TRUE)
#[1] "one fish two fish red fish blue dog"
This should also work with str_replace
str_replace(mystring, patfn(2), "\\1dog")
#[1] "one fish two dog red fish blue fish"
str_replace(mystring, patfn(3), "\\1dog")
#[1] "one fish two fish red dog blue fish"
Based on the pattern/replacement mentioned above, we can create a new function to do most of the options
replacerFn <- function(String, word, rword, n){
stopifnot(n >0)
pat <- sprintf(paste0("^((.*?\\b", word, "\\b.*?){%d})\\b",
word,"\\b"), n-1)
rpat <- paste0("\\1", rword)
if(n >1) {
stringr::str_replace(String, pat, rpat)
} else {
stringr::str_replace(String, word, rword)
}
}
replacerFn(mystring, "fish", "dog", 1)
#[1] "one dog two fish red fish blue fish"
replacerFn(mystring, "fish", "dog", 2)
#[1] "one fish two dog red fish blue fish"
replacerFn(mystring, "fish", "dog", 3)
#[1] "one fish two fish red dog blue fish"
replacerFn(mystring, "fish", "dog", 4)
#[1] "one fish two fish red fish blue dog"