Have a look at what stringi::stri_replace_last_regex
does:
Replaces with the given replacement string last substring of the input that matches a regular expression
What does your _ABC.*$
pattern match inside _AB:C-_ABCDEF_ABC:45_ABC:454:
? It matches the first _ABC
(that is right after C-
) and all the text after to the end of the line (.*$
grabs 0+ chars other than line break chars to the end of the line). Hence, you only have 1 match, and it is the last.
Solutions can be many:
1) Capturing all text before the last occurrence of the pattern and insert the captured value with a replacement backreference (this pattern does not have to be anchored at the end of the string with $
):
sub("(.*)_ABC.*", "\\1_CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:")
2) Using a tempered greedy token to make sure you only match any char that does not start your pattern up to the end of the string after matching it (this pattern must be anchored at the end of the string with $
):
sub("(?s)_ABC(?:(?!_ABC).)*$", "_CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:", perl=TRUE)
Note that this pattern will require perl=TRUE
argument to be parsed with a PCRE engine with sub
(or you may use stringr::str_replace
that is ICU regex library powered and supports lookaheads)
3) A negative lookahead may be used to make sure your pattern does not appear anywhere to the right of your pattern (this pattern does not have to be anchored at the end of the string with $
):
sub("(?s)_ABC(?!.*_ABC).*", "_CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:", perl=TRUE)
See the R demo online, all these three lines of code returning _AB:C-_ABCDEF_ABC:45_CBA
.
Note that (?s)
in the PCRE patterns is necessary in case your strings may contain a newline (and .
in a PCRE pattern does not match newline chars by default).