【问题标题】:R - replace last instance of a regex match and everything afterwardsR - 替换正则表达式匹配的最后一个实例以及之后的所有内容
【发布时间】:2023-03-23 08:28:01
【问题描述】:

我正在尝试使用正则表达式替换短语的最后一个实例(以及该短语之后的所有内容,可能是 any 字符):

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(),但没有奏效。

任何想法我哪里出错了?

【问题讨论】:

  • 使.* 不贪婪,它应该可以工作。 _ABC.*?$
  • 你能举出更多例子吗?

标签: r regex


【解决方案1】:

一种解决方案是:

sub("(.*)_ABC.*", "\\1_CBA", Input)
[1] "_AB:C-_ABCDEF_ABC:45_CBA"

【讨论】:

    【解决方案2】:

    看看stringi::stri_replace_last_regex做了什么:

    用给定的替换字符串替换匹配正则表达式的输入的最后一个子字符串

    您的_ABC.*$ 模式在_AB:C-_ABCDEF_ABC:45_ABC:454: 中匹配什么?它匹配 first _ABC(即在 C- 之后)和行尾之后的所有文本(.*$ 抓取除换行符之外的 0+ 个字符到末尾线)。因此,您只有 1 个匹配项,它是 最后一个

    解决方案可以有很多:

    1) 捕获模式最后一次出现之前的所有文本,并使用替换反向引用插入捕获的值(此模式不必使用$ 锚定在字符串的末尾):

    sub("(.*)_ABC.*", "\\1_CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:")
    

    2) 使用tempered greedy token 确保您只匹配任何在匹配后不开始模式直到字符串末尾的字符(此模式必须用$ 锚定在字符串的末尾):

    sub("(?s)_ABC(?:(?!_ABC).)*$", "_CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:", perl=TRUE)
    

    请注意,此模式需要使用带有 sub 的 PCRE 引擎解析 perl=TRUE 参数(或者您可以使用由 ICU 正则表达式库驱动并支持前瞻的 stringr::str_replace

    3) 可以使用负前瞻来确保您的模式不会出现在模式右侧的任何位置(此模式不必用$ 锚定在字符串的末尾):

    sub("(?s)_ABC(?!.*_ABC).*", "_CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:", perl=TRUE)
    

    查看R demo online,所有这三行代码都返回_AB:C-_ABCDEF_ABC:45_CBA

    请注意,PCRE 模式中的 (?s) 是必需的,以防您的字符串可能包含换行符(并且 PCRE 模式中的 . 默认情况下与换行符不匹配)。

    【讨论】:

      【解决方案3】:

      可以说最安全的做法是使用负前瞻来查找最后一次出现:

      _ABC(?:(?!_ABC).)+$
      

      Demo

      gsub("_ABC(?:(?!_ABC).)+$", "_CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:", perl=TRUE)
      [1] "_AB:C-_ABCDEF_ABC:45_CBA"
      

      【讨论】:

      • 你的(?:.(?!_ABC))+ 调和的贪婪令牌是corrupt
      • @WiktorStribiżew 谢谢!以后我一定会看看在哪里放置.
      【解决方案4】:

      使用gsub 和反向引用

      gsub("(.*)ABC.*$", "\\1CBA","_AB:C-_ABCDEF_ABC:45_ABC:454:")
      [1] "_AB:C-_ABCDEF_ABC:45_CBA"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-12-29
        • 1970-01-01
        • 2019-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多