(1) sub This can be done in one regex with sub :
> sub("(^(.*?-){4}.*?)-(.*?-.*?)-", "\\1|\\3||", txt, perl = TRUE) [1] "aaa-aaa-aaa-aaa-aaa|aaa-aaa||aaa-aaa-aaa"
(2) sub twice or this option, which calls sub twice:
> 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 or this variation that creates a sub.fun function that makes one substitution. it uses fn$ from gsubfn package to replace n-1 , pat and value with sub arguments. First define the specified function and then call it twice.
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"
(We could change the arguments to sub in the body of sub.fun , using paste or sprintf to give a basic R-solution, but at the cost of some extra verbosity.)
This can be reformulated as a replacement function giving this nice sequence:
"sub.fun<-" <- sub.fun tt <- txt
(4) gsubfn Using gsubfn from the gsubfn package , we can use a particularly simple regular expression (its just a "-" ), and the code has a fairly straightforward structure. We perform proto replacement. The protocol object containing this method is passed in place of the replacement string. The simplicity of this approach arises from the fact that gsubfn automatically makes the count variable available to such methods:
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"
UPDATE: some fixes.
UPDATE 2: Added approach to replacing function (3).
UPDATE 3: added pat argument to sub.fun .