【问题标题】:Conditional regular expressions in stringrstringr 中的条件正则表达式
【发布时间】:2018-09-06 11:15:39
【问题描述】:

我想知道如何在R中实现一个条件正则表达式,这个好像PERL可以实现:

?(if)then|else

但是,我无法弄清楚如何在 R 中实现这一点。举个简单的例子,假设我有以下字符串:

c('abcabd', 'abcabe')

我希望正则表达式匹配"bd"(如果存在),否则匹配"bc",然后将其替换为"zz"。因此,我希望上面的字符串是:

c('abcazz', 'azzabe')

我已经尝试过使用substr_replace 这两种方法似乎都不起作用。看来sub中我的语法可能有误:

sub('b(?(?=d)d|c)', 'zz', c('abcabe','abcabd'), perl=TRUE)
[1] "azzabe" "azzabd"

逻辑是“匹配b,如果后面跟着d匹配d,否则匹配c”。使用str_replace,我得到错误:

str_replace(c('abcabe','abcabd'), regex('b(?(?=d)d|c)'), 'zz')
Error in stri_replace_first_regex(string, pattern, fix_replacement(replacement),  : 
Use of regexp feature that is not yet implemented. (U_REGEX_UNIMPLEMENTED)

我主要使用stringr,因此更喜欢使用str_replace 的解决方案,但也欢迎使用sub 的解决方案。

【问题讨论】:

  • 在发布的答案中,我使用了sub(),您可以将其转换为str_replacestr_replace(c('abcabe','abcabd'), regex('^(.*)bd|bc'), '\\1zz')
  • 谢谢!我仍在努力理解您发布的条件正则表达式,但关于这个替代方案,这就是正则表达式总是更喜欢贪婪选项的原因,即。什么匹配最长的字符串?
  • Regex 引擎会尝试第一个路径,如果失败则尝试下一个立即可用的路径。在^(.*)bd 中,引擎会遍历所有字符,如果存在bd,则引擎不会尝试交替的另一端(已经找到匹配项,满意),但如果失败则查找bc。这会导致引擎不会错过匹配 bd 之前的机会 bc 也是。
  • 太好了,我想我现在明白了。我相信正在发生的事情是正则表达式逐个字符地搜索匹配项,使用交替的顺序 | 来确定优先级,因此为什么 ^(.*)bd|bc 有效但 bd|bc 无效。
  • bd|bc 这是b[cd] 的一种奇特方式(但顺序很重要)使引擎在每个步骤中都有 2 个直接选择。如果接下来的两个字符不是bd,它将尝试bc,并在找到匹配项后立即停止。

标签: r regex stringr


【解决方案1】:

你快到了,但你应该在每一步都有条件模式真断言:

(?(?=.*bd)bd|bc)

Live demo

你甚至不需要条件正则表达式:

^(.*)bd|bc

R 代码:

sub('^(.*)bd|bc', '\\1zz', c('abcabe','abcabd'))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-27
    • 2017-02-27
    • 1970-01-01
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 2011-04-10
    相关资源
    最近更新 更多