2

Pythonファイルからすべての関数をフィルタリングする正規表現を(ここでいくつかの大きな助けを借りて)書きました。だから今、私の上司は、OpenSessionを含み、 Session.Close()を含まない関数だけを望んでいます。

ルックアラウンドの記事を読んだのですが、正直、何度読んでも慣れません。しかし、正規表現の理解が一般的に欠如していると思います。なんでもいい...

私の試行はすべて失敗し、最後の試行は次のとおりです。(?is)def\s*(?<name>\w+)\s*\((?<parameter>[^)]+)\)\s*:\s*(?:\r?\n)+(?<body>(?<=OpenSession?).*?(?=Session\.Close?))(?=\r?\ndef|$)

誰かが私を助けて、手順を説明してくれるので、そこから学ぶことができますか?

4

1 に答える 1

5

OpenSessionすべての関数を取得してから、 を含むか含まないかでフィルター処理する方が確かに簡単です (読みやすく、保守しやすくなります) Session.Close()。でも可能です。bodyここでは、あなたの表現の部分だけに焦点を当てています。OpenSession到来があるかどうかを確認するために、それを look aheadに入れます。ただし、先読みは現在の位置のみをチェックするため、その間に任意の多くの文字を許可する必要があります。

(?=.*OpenSession)

OpenSession問題は、これが次の関数で見つかる可能性があることです。.*したがって、 が次の を通過できないことを確認する必要がありdefます。defそのためには、各文字を消費する前に、それが(別の否定的な 先読みで)の開始をマークしていないことを確認する必要があります。

(?=(?:(?!def).)*OpenSession)

そのため、含まれていない場合、パターンは関数と一致しませんOpenSession。を含む関数を除外するためSession.Closeに、先読みで使用したのと同様のトリックを使用します。defを超えることなく、次へと到達しようとしますSession.Close

(?=(?:(?!def).)*OpenSession)(?:(?!Session[.]Close).)*?

元のパターンの最後にある先読みにより、この方法で関数本体全体を使用できたことを確認できます。また、貪欲でない繰り返しを避けることで、おそらくパフォーマンスをわずかに改善できることに注意してください。defこれは、2 番目の先読みにも追加することで実行できます。

(?=(?:(?!\r?\ndef).)*OpenSession)(?:(?!Session[.]Close|\r?\ndef).)*

したがって、式は次のようになります。

(?is)def\s+(?<name>\w+)\s*\((?<parameter>[^)]+)\)\s*:\s*(?:\r?\n)+(?<body>(?=(?:(?!\r?\ndef).)*OpenSession)(?:(?!Session[.]Close|\r?\ndef).)*)(?=\r?\ndef|$)

ルックアラウンドの最後にを使用して何を達成したかったのかはわかりませんが?、最後の文字をオプションにしただけです。

また、関数内に を含む複数行の文字列が含まれている可能性があるため、このパターンは一般的に少し危険であることに注意してください。\ndefこの場合、正規表現は関数全体を返しません。

HamZa がコメントで述べたように、 、 、 につまずかないように、 、 、 の周りに単語境界を配置することをお勧め\bします。OpenSessionSession.ClosedefgetOpenSession()Session.Closeddefine

于 2013-08-15T08:49:07.937 に答える