红宝石1.9.3对2.0.0的正则表达式负面预测

时间:2014-04-11 05:53:39

标签: ruby regex regex-negation

我需要匹配以"bar"结尾但不以"foo"开头的数组成员,并将结果放入新数组中。

查看1.9.3和2.0.0的文档,它们似乎支持使用相同语法的负面预测。负面的预测工作正如我在ruby 2.0.0中预期的那样,但似乎在ruby 1.9.3中不起作用:

["foo a.bar", "b.bar"].grep(/(?!^foo\s).*\.bar$/)
# => ["b.bar"]              (ruby 2.0.0)
# => ["foo a.bar", "b.bar"] (ruby 1.9.3)

此基础架构上的ruby版本将在4个月内升级,但不能更快地更改版本。我怎样才能在1.9.3中完成这项工作,最好继续在2.0中工作?

3 个答案:

答案 0 :(得分:7)

更好地使用它,看起来更有说服力:

matched = array.grep(/^(?!foo\s).*\.bar$/)

NOT以foo开头

这将适用于2.1.1和1.9.3

只有你想知道我做了什么:

# ruby-1.9.3-p362
array = ["foo a.bar", "b.bar"] 
# => ["foo a.bar", "b.bar"] 
matched = array.grep(/(?!^foo\s).*\.bar$/)
# => ["foo a.bar", "b.bar"] 
matched = array.grep(/^(?!foo\s).*\.bar$/)
# => ["b.bar"] 
matched = array.grep(/(?!^foo\s).*\.bar$/)
# => ["foo a.bar", "b.bar"]

# ruby-2.1.1
array = ["foo a.bar", "b.bar"] 
# => ["foo a.bar", "b.bar"] 
matched = array.grep(/(?!^foo\s).*\.bar$/)
# => ["b.bar"] 
matched = array.grep(/^(?!foo\s).*\.bar$/)
# => ["b.bar"] 

答案 1 :(得分:4)

如果在生产服务器上绑定的ruby版本中似乎存在问题,那么简单的解决方案就是不使用负面预测。如果您的示例足够特别,您可以使用select和方便的String方法:

array.select {|str| !str.starts_with?('foo') && str.ends_with?('bar') }

答案 2 :(得分:3)

这是你的正则表示错误,而不是Ruby。 Ruby 2似乎有点宽容,是全部。

起始锚点(^)应该是之前的,而不是它。当它在行的开头不匹配foo时,正则表达式引擎向前突然移动一个位置并再次尝试。它不再是字符串的开头,因此^不匹配,否定前瞻报告成功,正则表达式匹配oo a.bar。 (这是一个非常常见的错误。)