【问题标题】:R vs sed regex greedinessR vs sed 正则表达式贪婪
【发布时间】:2013-07-19 05:08:56
【问题描述】:

我不太明白为什么这不会导致 "test" 并希望得到解释:

a = "blah test"
sub('^.*(test|$)', '\\1', a)
# [1] ""

将其与sed 表达式进行比较:

echo 'blah test' | sed -r 's/^.*(test|$)/\1/'
# test
echo 'blah blah' | sed -r 's/^.*(test|$)/\1/'
#

Fwiw,以下实现了我在R中想要的(相当于上面的sed结果):

sub('^.*(test)|^.*', '\\1', a)

【问题讨论】:

  • @agstudy 我正在尝试匹配 test 或行尾 - 正如您所看到的 sed 理解该逻辑。我不明白你为什么这么说(test|$) == $?我添加了我想要的编辑。
  • @agstudy 强调我不理解您写的内容,尝试运行sub('(test|$)', 'bb', a),R 肯定不会将其解释为与sub('$', 'bb', a) 相同
  • 虽然这不会改变结果,但需要注意的一点是 R 使用扩展的正则表达式,而 sed(Ubuntu 12.04 64 位上的 4.2.1)默认使用基本的正则表达式。正如我所说,echo 'blah test' | sed -r 's/^.*(test|$)/\1/') 产生相同的输出。
  • @JoshuaUlrich 谢谢,已更改

标签: regex r sed


【解决方案1】:

您需要将^.* 标记为non-greedy

> sub('^.*?(test|$)', '\\1', "blah test")
[1] "test"
> sub('^.*?(test|$)', '\\1', "blah blah")
[1] ""

【讨论】:

  • @JoshuaUlrich,我不确定我的意思。也许我的意思是懒惰
  • @GSee 是的,你让.* lazy.
  • @GSee 谢谢,这当然很有用,但似乎sed 对懒惰/贪婪有不同的想法,因为您链接中的示例对sed 来说是贪婪的方式:@987654328 @结果bbb removed;我猜条件句的贪婪有不同的实现。
  • 是否存在一种“正确”而另一种不正确的感觉?从那个链接我得到的印象是sed 做错了吗?
  • Lazynon-greedyreluctant 在这种情况下都是同一个意思。但是 optional 不适用,所以我删除了。
【解决方案2】:

regex engine 的开头匹配字符串末尾的所有字符,即 greedy .*,然后它尝试匹配 (test|$),即字符串文字 'test ' 或字符串的结尾。由于.*的第一个greedy匹配匹配了所有字符,它back-references一个字符然后再次尝试匹配(test|$),这里$匹配字符串的结尾。

使您的匹配结果成为end of line character

我认为sed 使用 POSIX NFA,它试图在 Alternation 中找到最长的匹配,这与 R 不同,后者似乎使用 Traditional NFA

【讨论】:

  • 谢谢;我是否误解了传统与 POSIX NFA 的关系,因为据我所知,(set|setvalue)(setvalue|set)sedR 中的匹配方式完全相同(在'setvalue'上测试匹配)......?
  • 虽然两者似乎都使用 NFA,但它们的实现可能会略有不同,在某些情况下证明一个比另一个更快。另请阅读stackoverflow.com/questions/12100588/…
猜你喜欢
  • 2010-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-03
  • 2011-04-27
相关资源
最近更新 更多