2011-01-18 2 views
8

(注意:!タイトルはクリアしていないようだ - 誰かがこれを言い換えることができる場合、私はそれをすべてだ)、この正規表現を考える1文字のマッチングに交替または文字クラスを使用しますか?

(.*_e\.txt)、いくつかのファイル名と一致し、私はいくつかの他の単一の文字を追加する必要があります接尾辞はeに加えて私は文字クラスを選択する必要がありますか、またはこれに代わるものを使うべきですか?

a)に(.*(e|f|x)\.txt)、または

B)(.*[efx]\.txt)

+1

あなたはハード__any__パフォーマンスを測定するためにプッシュされます両者の違い。心配するのを止めて、最も明瞭なものを使用してください。 – bobbogo

+1

@bobbogo:質問はパフォーマンスに関してはっきりとしたものではなく、ちょうど「より良い」+理由についてです。 –

+0

@Mrtin:私は完全に同意します。明確なコードが優先事項です。 – bobbogo

答えて

16

使用:

"より良い" ようで、次の2つのどちらであり、

をなぜ(あるいは、それは本当に??問題ではありません) [efx] - それはまさに文字クラスのために設計されたものです。したがって、最も読みやすく、最短のソリューションでもあります。

私はそれが速いのかどうかわかりませんが、そうでなかったら私は非常に驚くでしょう。間違いなく遅くなることはありません。

私の推論(今までになくて正規表現エンジンを書いたので、これは純粋な推測です):

正規表現トークン[abc]は、正規表現エンジンの単一段階で適用されます:「次の文字がaの一つです、b、またはc? "

(a|b|c)は、しかし、チェック

  • 、必要であれば、それは aを一致させることが可能です場合、バックトラッキングのための文字列内の現在位置を覚えて

    • に正規表現エンジンに指示します。そうなら、成功する。そうでない場合:
    • bと一致するかどうかを確認してください。そうなら、成功する。そうでない場合:
    • cと一致するかどうかを確認してください。そうなら、成功する。そうでない場合:
    • あきらめます。
    1

    1文字の場合、それは重要ではないような最小限の違いがあります。 (たくさんの操作をしていない限り)

    ただし、読みやすさ(およびわずかなパフォーマンスの向上)のために、文字クラスメソッドを使用する必要があります。

    さらに詳しい情報については、丸括弧(を開いてPerlにその現在の位置のバックトラッキングを開始させます。これは、それ以上の一致がないので、本当にあなたの正規表現を必要としません。文字クラスはこれをしません。ここで

    +1

    独立したサブグループである '(?> ...)'を使って、グループ内のバックトラックをある程度制御できます。そうすれば、グループ自体が再考されることはありません。しかし、使用するのはちょっと難しいです。 – tchrist

    +0

    @tchrist:はるかに簡単ですが、単純な '(?:...)'を使うのは、サブグループを捕捉したくないときです。 –

    11

    がベンチマークです:

    tchristコメントに応じて更新

    、違いがより重要である

    #!/usr/bin/perl 
    use strict; 
    use warnings; 
    use 5.10.1; 
    use Benchmark qw(:all); 
    
    my @l; 
    foreach(qw/b c d f g h j k l m n ñ p q r s t v w x z B C D F G H J K L M N ñ P Q R S T V W X Z/) { 
        push @l, "abc$_.txt"; 
    } 
    
    my $re1 = qr/^(.*(b|c|d|f|g|h|j|k|l|m|n|ñ|p|q|r|s|t|v|w|x|z)\.txt)$/; 
    my $re2 = qr/^(.*[bcdfghjklmnñpqrstvwxz]\.txt)$/; 
    my $cpt; 
    
    my $count = -3; 
    my $r = cmpthese($count, { 
        'alternation' => sub { 
         for(@l) { 
          $cpt++ if $_ =~ $re1; 
         } 
        }, 
        'class' => sub { 
         for(@l) { 
          $cpt++ if $_ =~ $re2; 
         } 
        } 
    }); 
    

    結果:

       Rate alternation  class 
    alternation 2855/s   --  -50% 
    class  5677/s   99%   -- 
    
    +2

    それは興味深い - そして、私は、有用だ - イラストレーションです。しかし、それはたくさんあります。入力データを変更すると、パターンを変更した場合と同じように、異なるパフォーマンスが得られます。たとえば、 '[bcdfghjklmn?pqrstvwxz]' vs '(b | c | d | f | g | h | j | k | l | m | n |ñ| p | q | r | s | t | v | w | x | z) 'の方がずっと長く、おそらく異なるパフォーマンス特性を示すはずです。 – tchrist

    +0

    '$ re1'と' $ re2'が同じではないので、 'utf8;'プラグマを使うべきだと思います;-) –