2

C# の私のプロジェクトでは、日付のテキストを解析しています。日付はさまざまな形式にすることができます。目的は、多数の日付形式エラーを見つけて修正することです。さまざまな日付形式があるということは、一連の定義された日付形式が実現不可能であることを意味します。もともと、入力文字列に 1 つずつ適用される約 10 個の正規表現のセットがありました。これは機能的には問題ありませんでしたが、文字列が 200 KB のテキストに達すると、関数が約 150 ミリ秒かかるため、パフォーマンスが問題になりました。

日付正規表現を日付である部分文字列にのみ適用することで、パフォーマンスを大幅に改善できることがわかりました。したがって、すべての日付に英語の月名が必要な場合は、次の正規表現を使用します

\b(January|February|March|April|May|June|July|August|September|October|November|December)\b

それらを見つけるでしょう。次に、月の周りのテキストを一致させるために部分文字列化を行った場合、全体的な関数のパフォーマンスは約 25 ミリ秒で、はるかに優れていました。ただし、部分文字列/ループの長さチェック コードが乱雑で、本当に良い解決策とは思えません。私が本当に欲しかったのは、月とその周りのテキストに一致する単一の正規表現でした。

.{0,25}\b(January|February|March|April|May|June|July|August|September|October|November|December)\b.{0,25}

機能的には問題ありません。ただし、この正規表現のパフォーマンスは、同じ長い入力文字列で一致を見つけるのに約 3500 ミリ秒かかります。

今、同様の正規表現

(?<=.{0,25})\b(January|February|March|April|May|June|July|August|September|October|November|December)\b.{0,25}

肯定的な後読みを使用すると、約15ミリ秒で一致が見つかります(バックトラッキングが非常に減少したため、私が受け入れ、ある程度理解している理由です)。ただし、月名の前後のテキストを一致結果に含める必要があるため、それは私の使用には適していません。

それで、私の質問は、後読みを使用するパフォーマンスを備えた正規表現を持つことができますが、一致結果内のすべてのテキストを提供する機能はありますか?

4

1 に答える 1

2

パフォーマンスの向上は幻想です。通常、次のようなもの.{0,25}は多くのバックトラックを引き起こします。これがパフォーマンスの低下を説明しています。ただし、後読みの内部に配置すると、貪欲な動作を停止し、バックトラックします。後読みは可能な限り最小の一致を探します。つまり、バックトラックなしで0文字が試行されます。これは、月名の前のゼロ文字に常に一致するため、後読みはまったく役に立たないことを意味します。

一致する月名の位置を使用して一致を見つけた後、コンテキストを抽出するとどうなるでしょうか。のそれぞれについてmatch、これらの位置の前後にあるおよびおよび サブストリングregex.Matches(str)を取得します。match.Indexmatch.Length

于 2013-01-05T10:20:17.937 に答える