正则表达式:匹配一个字符串到一个模式(可能不存在)

Aus*_*tin 4 python regex negative-lookahead

我正在尝试使用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)
Run Code Online (Sandbox Code Playgroud)

这是脚本目前唯一正在做的事情.

Tim*_*ker 6

你的问题在于,[^<>]+(?!-->)前瞻断言仅在This is a comment--匹配后尝试,当然它成功,因为-->在正则表达式引擎结束的位置没有.

因此,您必须检查字符串的每个位置的前瞻.对此的正确习惯通常是:

(?:(?!-->).)*
Run Code Online (Sandbox Code Playgroud)

或者,在你的情况下

(?:(?!-->)[^<>])*
Run Code Online (Sandbox Code Playgroud)

这将匹配除尖括号之外的任意数量的字符,直到-->出现或到达字符串的结尾.


ste*_*ema 5

您需要使用积极的前瞻,以确保此模式领先于您的匹配.

[^<>]+(?=-->)
Run Code Online (Sandbox Code Playgroud)

如果你想让它更通用,以便它也匹配其他标签的内容,你可以在前瞻断言中使用一个替换:

[^<>]+(?=-->|</)
Run Code Online (Sandbox Code Playgroud)

在Regexr上看到它

如果前方有" -->"或" </" ,则此正则表达式将停止.