4

Python で正規表現トークナイザーを使用して XML ドキュメントを解析しようとしています (これは有限集合なので、正規表現で十分です!)。コメントを適切に一致させるのに問題があります。

これらのコメントの形式<!--This is a comment-->は、コメント自体に英数字以外のあらゆる種類の文字 (「-」を含む) を含めることができる形式です。

コメントを次のトークンに分割するような方法でそれらを一致させたい:

<!--

This is a comment

-->

開始マーカーは簡単に取得でき、別の正規表現でそれを取得することに成功しましたが、コメントの正規表現自体が貪欲になりすぎて--、終了マーカーから取得しています。<Tag>This is text</Tag>ただし、この正規表現は、必ずしもコメントで囲まれているとは限らない文字列も取得する必要があるため、取得して正しく返すこともできるはずThis is textです。

これは、現在テキストに使用している正規表現です。

[^<>]+(?!-->)

他のThis is a comment--正規This is a comment表現が-->. ただし、この正規表現は通常のタグでは機能しますが、終了タグに「<」が存在するためThis is text、前の例から適切に返されます。

否定先読みを適切に使用してはならないことはわかっています。ここで私が間違っていることについてのアイデアはありますか? を試しまし[^<>]+(?=-->)たが、この形式のコメントではないもの (通常のタグなど) には一致しません。はそのパターンを見たときにマッチングを停止するだろうと考えましたが、その(?!-->)ようには機能しないようで、末尾の '>' が表示されるまでマッチングを続けます。

コンテキストのコードのセグメントを投稿する:

xml_scanner = re.Scanner([
    (r"  ",             lambda scanner,token:("INDENT", token)),
    (r"<[A-Za-z\d._]+(?!\/)>",  lambda scanner,token:("BEGINTAG", token)),
    (r"<\/[A-Za-z\d._]+(?!\/)>",  lambda scanner,token:("ENDTAG", token)),
    (r"<[A-Za-z\d._]+\/>",      lambda scanner,token:("INLINETAG", token)),
    (r"<!--",               lambda scanner,token:("BEGINCOMMENT", token)),
    (r"-->",                lambda scanner,token:("ENDCOMMENT", token)),
    (r"[^<>]+(?!-->)",         lambda scanner,token:("DATA", token)),
    (r"\r$", None),
])

for line in database_file:
    results, remainder = xml_scanner.scan(line)

これは、現時点でスクリプトが行っている唯一のことです。

4

2 に答える 2

7

あなたの問題は、[^<>]+(?!-->)では、先読みアサーションが一致した後にのみ試行され、正規表現エンジンが終了した位置にThis is a comment--ないため、もちろん成功することです。-->

したがって、文字列のすべての位置で先読みを確認する必要があります。これに対する適切な慣用句は、一般的に次のとおりです。

(?:(?!-->).)*

または、あなたの場合

(?:(?!-->)[^<>])*

これは、山かっこを除く任意の数の文字に一致するか-->、文字列の末尾に到達するまで一致します。

于 2013-06-13T14:02:19.820 に答える
5

このパターンが一致することを確認するには、肯定的な先読みを使用する必要があります。

[^<>]+(?=-->)

他のタグのコンテンツにも一致するように、より普遍的なものにしたい場合は、先読みアサーション内で代替を使用できます。

[^<>]+(?=-->|</)

ここでRegexrを参照してください

-->" " または " " が先にある場合、この正規表現は停止</します。

于 2013-06-13T13:56:36.280 に答える