我尝试使用正则表达式替换短语的最后一个实例(以及该短语之后的所有内容,可能是任何字符):
stringi::stri_replace_last_regex("_AB:C-_ABCDEF_ABC:45_ABC:454:", "_ABC.*$", "CBA")
但是,我似乎无法让refex正常运行:
Input: "_AB:C-_ABCDEF_ABC:45_ABC:454:"
Actual output: "_AB:C-CBA"
Desired output: "_AB:C-_ABCDEF_ABC:45_CBA"
我也尝试过gsub()但是没有用。
我出错的任何想法?
答案 0 :(得分:3)
一个解决方案是:
sub("(.*)_ABC.*", "\\1_CBA", Input)
[1] "_AB:C-_ABCDEF_ABC:45_CBA"
答案 1 :(得分:1)
使用gsub
并返回引用
gsub("(.*)ABC.*$", "\\1CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:")
[1] "_AB:C-_ABCDEF_ABC:45_CBA"
答案 2 :(得分:1)
可以说最安全的事情是使用负向前瞻来找到最后一次出现:
_ABC(?:(?!_ABC).)+$
gsub("_ABC(?:(?!_ABC).)+$", "_CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:", perl=TRUE)
[1] "_AB:C-_ABCDEF_ABC:45_CBA"
答案 3 :(得分:0)
看看stringi::stri_replace_last_regex
做了什么:
替换给定的替换字符串与正则表达式匹配的输入的最后一个子字符串
_ABC.*$
模式在_AB:C-_ABCDEF_ABC:45_ABC:454:
内匹配的内容是什么?它匹配第一个 _ABC
(就在C-
之后)和所有文本之后到行尾(.*$
抓取0+以外的字符换行符号到行尾()。因此,您只有1个匹配,并且它是 last 。
解决方案可以很多:
1)在最后一次出现模式之前捕获所有文本,并使用替换反向引用插入捕获的值(此模式不必锚定在带有$
的字符串末尾):
sub("(.*)_ABC.*", "\\1_CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:")
2)使用tempered greedy token确保只匹配任何未启动模式的字符,然后匹配字符串的结尾(此模式必须锚定在字符串的末尾{ {1}}):
$
请注意,此模式需要使用sub("(?s)_ABC(?:(?!_ABC).)*$", "_CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:", perl=TRUE)
的PCRE引擎解析perl=TRUE
参数(或者您可以使用ICU正则表达式库驱动的sub
并支持前瞻)
3)可以使用负前瞻来确保您的模式不会出现在模式右侧的任何位置(此模式不必使用stringr::str_replace
锚定在字符串的末尾):< / p>
$
请参阅R demo online,这三行代码返回sub("(?s)_ABC(?!.*_ABC).*", "_CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:", perl=TRUE)
。
请注意,如果您的字符串可能包含换行符,则PCRE模式中的_AB:C-_ABCDEF_ABC:45_CBA
是必需的(默认情况下,PCRE模式中的(?s)
与新行字符不匹配。