2012-01-20 11 views
6

私はクラスで約100回Regexコールを持っていますが、すべてのコールはテキストプロトコルのさまざまな種類のデータをカバーしますが、私は多くのファイルを持ち、分析に基づいていますregexは私のコードの88%Regexのより速い置き換え

多くのこの種のコード:

{ 
    Match m_said = Regex.Match(line, @"(.*) said,", RegexOptions.IgnoreCase); 
    if (m_said.Success) 
    { 
    string playername = ma.Groups[1].Value; 
    // some action 
    return true; 
    } 
} 

{ 
    Match ma = Regex.Match(line, @"(.*) is connected", RegexOptions.IgnoreCase); 
    if (ma.Success) 
    { 
    string playername = ma.Groups[1].Value; 
    // some action 
    return true; 
    } 
} 
{ 
    Match ma = Regex.Match(line, @"(.*): brings in for (.*)", RegexOptions.IgnoreCase); 
    if (ma.Success) 
    { 
    string playername = ma.Groups[1].Value; 
    long amount = Detect_Value(ma.Groups[2].Value, line); 
    // some action 
    return true; 
    } 
} 

は、他のいくつかの高速化ソリューションでRegexを置き換えるためにどのような方法か?ループでテストされている正規表現については

+1

私はあなたが使用している正規表現の種類に依存すると思う...いくつかのサンプルを提供! –

答えて

8

、それは多くの場合、より高速プリコンパイルループとちょうどテストループの内部それらの外彼らにあります。

最初に異なる正規表現をそれぞれのパターンで宣言し、2番目のステップでテストするテキストをMatch()と呼び出す必要があります。

+1

RegExクラスにキャッシュがありませんか? –

+0

@HenkHolterman:確かに。私はちょうどその文書でチェックした。 (私は、キャッシュ機構を提供しないPCREにもっと慣れています。)キャッシュは、OPによって作られた静的な 'Regex.Match()'呼び出しのために働くべきです。または、Regexpsが多すぎると、 'Regex.CacheSize'がパフォーマンスを向上させるために探求する道です(しかし私は疑います)? – Seki

+0

おかげで10倍速くなりました;-)))))) – Svisstack

1

あなたは正規表現事前に正規表現をコンパイルしてみてくださいまたは1(モンスター)にすべての個々の正規表現の表現を組み合わせることを検討できます。

Match m_said = Regex.Match(line, 
      @"(.*) (said|(is connected)|...|...),", 
      RegexOptions.IgnoreCase); 

あなたはその後、試合の種類が起こったかを決定するために、第2のキャプチャグループをテストすることができます。

+0

これは、ファイルを1回だけスキャンしようとする唯一の回答です。 –

+0

可能性のあるテキストに応じて、@ "(。*)said"というバージョンに問題がある可能性があります:もしUser17が "私はすでにそれを言っています"と言ったらどうでしょうか? - 正規表現は間違っているでしょう " –

+1

私はそれをすることはできません、行は、例えばXのコマンドY以外の様々な形式を持っています。 – Svisstack

1

私は正規表現を使用すると、可能性があり、物事の多くを行うが、ここであなたの正規表現をプリコンパイルからベンチマークセクション別に

+1

私のサイトはただの眼球をレイプしたと思う。 – adelphus

+0

あなたはそれについて正しいです-_- –

3

でのstring.Split

http://www.dotnetperls.com/split 対char.Split対正規表現とのベンチマークであることを知ってより正確な正規表現を書くことで、(おそらくはるかに多くの)パフォーマンス上の利点が得られます。この点で、.*はほとんど常に悪い選択である:

(.*) is connected意味:まず、それはis connectedを一致させることが可能ですまで、一度に1つの文字をバックトラック、その後、(それは.*部分です)文字列全体と一致します。

文字列の長さが非常に短いか、またはis connectedが文字列の末尾に非常に近いと表示されない限り、時間がかかるバックトラックがたくさんあります。

許可されている一致を絞り込むことができれば、パフォーマンスを向上させることができます。

たとえば、英数字のみを使用できる場合は、(\w+) is connectedが有効です。空白以外の文字の場合は、(\S+) is connectedを使用します。等、有効なマッチのルールに応じて。

具体的な例では、キャプチャされたマッチで何もしていないように見えるので、正規表現を完全に削除して固定部分文字列を探すこともできます。どの方法が最終的に最速になるかは、実際の入力と要件に大きく依存します。

+0

ガー!私はregexpsの大きな強みの1つについてDFAsにコンパイルすることができ、バックトラックは必要ないとのコメントを書こうとしていました。しかし、私はregexpsの.NET実装のためのドキュメントを見て、[*あなたは正しい!*](http://msdn.microsoft.com/en-us/library/dsy130b4.aspx) –

2

式を再利用できるかどうか、またはメソッドが複数回呼び出されたかどうかはわかりませんが、そうであれば正規表現をプリコンパイルする必要があります。あなたのサンプルで

private static readonly Regex xmlRegex = new Regex("YOUR EXPRESSION", RegexOptions.Compiled); 

、この方法は、それが表現「をコンパイル」が使用されるたびに、しかし、式はconstのであるとして、これはunneccesaryです:これを試してみてください。これはコンパイルされたこのコンパイル済みのものです。最初に式にアクセスすると少し遅くなるという欠点があります。

+1

ありがとう;-)これはこの静的フィールドの良い答えです – Svisstack

関連する問題