9

関連するすべての投稿を読み、インターネットを精査しましたが、これは本当に私を打ち負かしています.

日付を含むテキストがあります。
日付をキャプチャしたいのですが、特定のフレーズが前にある場合はキャプチャできません。

簡単な解決策は、正規表現に否定的な後読みを追加することです。

以下にいくつかの例を示します (findall を使用)。
「現在」というフレーズが前にない場合にのみ、日付をキャプチャしたい。

19-2-11
何か 何か 15-4-11
など 29-5-11 など

これが私の正規表現です:

(?<!as of )(\d{1,2}-\d{1,2}-\d{2})

予想された結果:

['19-2-11']
['15-4-11']
[]

実績:

['19-2-11']
['15-4-11']
['9-5-11']

29 ではなく 9 であることに注意してください。最初のパターンの\d{1,2}ように堅実なものに変更すると、次のようになります。\d{2}

bad regex for testing: (?<!as of )(\d{2}-\d{1,2}-\d{2})

その後、期待どおりの結果が得られます。もちろん、1 桁の日だけでなく 2 桁の日も一致させたいので、これではダメです。

どうやら私の否定的な後読みは非常に貪欲です - 私の日付キャプチャよりももっと、それから数字を盗んで失敗しています。私は思いつく限りの貪欲さを正すあらゆる手段を試しましたが、これを正す方法がわかりません。

日付のキャプチャを最大限の貪欲に一致させてから、否定的な後読みを適用したいと思います。これは可能ですか?私の問題は、否定的な後読みの適切な使用のように見え、過度に複雑ではありませんでした。必要に応じて別の方法で達成できると確信していますが、これを行う方法を学びたいと思います。

Python の否定的な後読みをあまり欲張らないようにするにはどうすればよいですか?

4

3 に答える 3

8

これは貪欲とは何の関係もありません。貪欲さは、正規表現が一致するかどうかに関係なく変わりません。検索が実行される順序のみが変わります。ここでの問題は、不要な一致を避けるために正規表現をより具体的にする必要があることです。

それを修正するには、一致の直前に単語境界を要求できます。

(?<!as of )\b(\d{1,2}-\d{1,2}-\d{2})
#          ^^ add this
于 2012-05-02T20:27:37.030 に答える
1

その理由は、後ろ姿が貪欲だからではありません。これは、正規表現エンジンが可能なすべての位置でパターンを一致させようとするために発生します。

such and such as of 29-5-11最初は正常に一致(?<!as of )しましたが、一致しなかったフレーズを進め\d{1,2}ます。

しかし、その後、エンジンは自分自身をその位置に見つけますsuch and such as of !29-5-11(でマークされてい!ます)。しかし、ここでは一致しません(?<!as of )

そして、それは次の位置に進みます:such and such as of 2!9-5-11。正常に一致した場所(?<!as of )、次に\d{1,2}

それを回避する方法は?

一般的な解決策は、パターンをできるだけ明確に定式化することです。

この場合、必要なスペースまたは文字列の先頭を数字の前に追加します。

(?<!as of)(?:^|\s+)(\d{1,2}-\d{1,2}-\d{2})

MarkByersのソリューションも非常に優れています。

正規表現エンジンがこのように動作し、望ましくない結果をもたらす理由を理解することは非常に重要だと思います。

ちなみに、スペースが2つ以上あると、上記の解決策は機能しません。ここsuch and such as of ! 29-5-11では、最初の位置が上記のパターンと一致しているため、機能しません。

それを避けるために何ができるでしょうか?

残念ながら、Pythonの正規表現エンジンのルックビハインドは数量詞+またはをサポートしていません*

最も簡単な解決策は、前にスペースがないことを確認することだと思います(?:^|\s+)(つまり、スペース以外のテキストの直後にすべてのスペースが消費され(?:^|\s+)ます(テキストがそうである場合はas of、前進を終了し、次の開始位置に戻って検索を開始します)検索されたテキストの次の位置でもう一度)。

re.search(r'(?<!as of)(?<!\s)(?:^|\s+)(\d{1,2}-\d{1,2}-\d{2})','such and such as of  29-5-11').group(1)
于 2012-05-02T20:49:12.770 に答える
-1

簡単な解決策は、正規表現を使用して日付を分離する前に、「現在」に一致するすべての行を破棄することです。

于 2012-05-02T21:15:37.927 に答える