0

Ruby1.9.3 を使用しています。私はこのプラットフォームの初心者です。

Regexpドキュメントから、以下を使用して作成できることを知りました。

  • %r{pattern}
  • /pattern/

styles上記の 2 つの間には、fastパターン マッチング シンボル、Area specifics( ***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(..)ここで、 との違いの 1 つを見つけました。これは、エスケープするため/../に使用する必要がないことです。実際の経験から他に何かありますか?\/

編集

@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 ベンチマークがここにインストールされていません。しかし、その 2 つの出力を知ることは興味深いことです。いずれかが出力されている場合は、端末で試して詳細をここに貼り付けていただけますか?

ありがとう

4

4 に答える 4

4

と にまったく違いは%r/foo/ありません/foo/

irb(メイン):001:0> %r[foo]
=> /foo/
irb(メイン):002:0> %r{foo}
=> /foo/
irb(メイン):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 での 2 つのテスト間で大幅に異なる回答を得ることは、同じものを指定する 2 つの構文的に異なる方法の実行時のパフォーマンスの違いを示します。私はそれが起こることを真剣に疑っています。


編集:

複数回実行すると、ランダム性が動作していることがわかります。今朝、コードを少し調整して、ベンチマーク全体で 5 つのループを実行できるようにしました。システムはテストの実行中にディスクをスキャンしていたので、少し時間がかかりましたが、2 回の実行の間にランダムな小さな違いが見られます。

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)

約 2 秒後に実行:

      # 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)

速度に一貫した違いはありません。

于 2013-01-17T04:49:25.687 に答える
2

%r(..)ここで、 との違いの 1 つを見つけました。これは、エスケープするため/../に使用する必要がないことです。\/

それが彼らの主な用途です。区切り文字によってセマンティクスが変わる文字列とは異なり、正規表現リテラル間の実際の違いは区切り文字自体だけです。

于 2013-01-16T10:24:57.937 に答える
1

%r 表記を使用すると、区切り記号として任意の記号を使用できます。たとえば、正規表現を次のいずれか (およびそれ以上) として記述できます。

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

これは、正規表現に多くの「/」が含まれている場合に役立ちます

注: 何を使用しても、既定の形式で保存されます。つまり、 %r:pattern: はデフォルトで /pattern/ になります

于 2013-01-16T13:00:42.600 に答える
1

このスレッドも参照してください。 Ruby %r{ } 式とこのドキュメントの 2 つの段落http://www.ruby-doc.org/core-1.9.3/Regexp.html

// の代わりに %r の後に任意の記号を区切り文字として使用することを除いて、違いはありません。

于 2013-01-16T10:37:14.490 に答える