在Ruby中的Regexp创建中,%r(..)与/../的区别如何?

时间:2013-01-16 10:17:39

标签: ruby regex ruby-1.9.3

我使用的是Ruby1.9.3。我是这个平台的新手。

从我知道的文档中我们可以使用以下内容制作Regexp

  • %r{pattern}
  • /pattern/

现在上面提到的两个stylesfast模式匹配符号的内容,区域细节(***can use/can't use restrictions***)等之间存在任何差异。

我发现如下:

irb(main):006:0> s= '2/3'
=> "2/3"
irb(main):008:0> /2\/3/ =~ s
=> 0
irb(main):009:0> %r(2/3) =~ s
=> 0
irb(main):010:0> exit

我在%r(..)/../之间发现了一个不同之处,我们不需要使用\来逃避/。你的实践经历还有吗?

修改

按照 @akashspeaking 的建议,我尝试了这个并找到了他说的话:

> re=%r(2/3)­
=> /2\/3/   # giving the pattern /../. Means Ruby internally converted this %r(..) to /../, which it should not if we created such regexp pattern manually.
> 

从上面可以看出,理论上%r(..)/../慢。

任何人都可以通过执行quickbm(10000000) { /2\­/3/=~s }quickbm(10000000) { %r(2/3) =~ s }来衡量执行时间来帮助我。我没有在这里安装所需的gem基准测试。但古玩要知道那两个的输出。如果有人 - 你可以试试终端并在此处粘贴详细信息吗?

由于

4 个答案:

答案 0 :(得分:4)

%r/foo//foo/完全没有区别。

irb(main):001:0> %r[foo]
=> /foo/
irb(main):002:0> %r{foo}
=> /foo/
irb(main):003:0> /foo/
=> /foo/

解释器在启动时将分析源脚本,两者都将转换为正则表达式,在运行时,它将是相同的。

唯一的区别是源代码,而不是可执行文件。试试这个:

require 'benchmark'

str = (('a'..'z').to_a * 256).join + 'foo'
n = 1_000_000

puts RUBY_VERSION, n
puts

Benchmark.bm do |b|
  b.report('%r') { n.times { str[%r/foo/] } }
  b.report('/') { n.times { str[/foo/] } }
end

哪个输出:

1.9.3
1000000

      user     system      total        real
%r  8.000000   0.000000   8.000000 (  8.014767)
/  8.000000   0.000000   8.000000 (  8.010062)

这是在运行10.8.2的旧MacBook Pro上。想一想,搜索的是6,656,000,000(26 * 256 * 1,000,000)个字符,并且两者都返回了基本相同的值。巧合?我想不是。

在计算机上运行它并获得在该CPU上的两个测试之间显着不同的答案将表明两种语法不同的指定相同事物的方式的运行时性能的差异。我严重怀疑会发生什么。


编辑:

多次运行会显示随机性。我调整了一下代码,使它在今天早上的基准测试中做了五个循环。系统在运行测试时正在扫描磁盘,所以它们需要更长时间,但它们在两次运行之间仍然显示出轻微的随机差异:

require 'benchmark'

str = (('a'..'z').to_a * 256).join + 'foo'
n = 1_000_000

puts RUBY_VERSION, n
puts

regex = 'foo'
Benchmark.bm(2) do |b|
  5.times do
    b.report('%r') { n.times { str[%r/#{ regex }/] } }
    b.report('/')  { n.times { str[/#{ regex }/] } }
  end
end

结果:

      # user     system      total        real
%r  12.440000   0.030000  12.470000 ( 12.475312)
/   12.420000   0.030000  12.450000 ( 12.455737)
%r  12.400000   0.020000  12.420000 ( 12.431750)
/   12.400000   0.020000  12.420000 ( 12.417107)
%r  12.430000   0.030000  12.460000 ( 12.467275)
/   12.390000   0.020000  12.410000 ( 12.418452)
%r  12.400000   0.030000  12.430000 ( 12.432781)
/   12.390000   0.020000  12.410000 ( 12.412609)
%r  12.410000   0.020000  12.430000 ( 12.427783)
/   12.420000   0.020000  12.440000 ( 12.449336)

大约两秒后运行:

      # user     system      total        real
%r  12.360000   0.020000  12.380000 ( 12.390146)
/   12.370000   0.030000  12.400000 ( 12.391151)
%r  12.370000   0.020000  12.390000 ( 12.397819)
/   12.380000   0.020000  12.400000 ( 12.399413)
%r  12.410000   0.020000  12.430000 ( 12.440236)
/   12.420000   0.030000  12.450000 ( 12.438158)
%r  12.560000   0.040000  12.600000 ( 12.969364)
/   12.640000   0.050000  12.690000 ( 12.810051)
%r  13.160000   0.120000  13.280000 ( 14.624694) # <-- opened new browser window
/   12.650000   0.040000  12.690000 ( 13.040637)

速度没有一致的差异。

答案 1 :(得分:2)

  

我在%r(..)/../之间找到了一个我们不需要的差异   使用\来逃避/

这是他们的主要用途。与字符串不同,字符串的分隔符改变了它们的语义,正则表达式文字之间唯一真正的区别就是分隔符本身。

答案 2 :(得分:1)

另请参阅此帖子The Ruby %r{ } expression以及此文档http://www.ruby-doc.org/core-1.9.3/Regexp.html

的2个段落

除了在%r之后使用任何符号作为分隔符而不是//

之外没有区别

答案 3 :(得分:1)

如果使用%r表示法,则可以使用任意符号作为分隔符。例如,您可以将正则表达式编写为以下任何一种(以及更多):

%r{pattern}
%r[pattern]
%r(pattern)
%r!pattern!

如果正则表达式包含大量“/”

,这可能很有用
  

注意:无论您使用什么,它都将以默认形式保存。即   %r:pattern:默认为/ pattern /