【问题标题】:Regex Negative Lookahead doesn't work as expectedRegex Negative Lookahead 无法按预期工作
【发布时间】:2015-03-13 04:56:07
【问题描述】:

我正在尝试捕获两个最接近的短语(包括这些短语)之间的文本,但在我的情况下,否定前瞻似乎不起作用。

所以,这是文本文件的一部分:

<in><il>plural</il> <if>aba*cus*es</if> <il>also</il> <if>aba*ci</if> <sound><wav>abaci001.wav</wav><wav>abaci002.wav</wav></sound> <pr>-ˌsaɪ</pr> <altpr>ˈæbəˌsaɪ</altpr></in>
<in><il>plural</il> <if>fau*nas</if> <il>also</il> <if>fau*nae</if> <sound><wav>fauna002.wav</wav></sound> <pr>ˈfɑ:ˌni:</pr></in>
<il>or</il> <if>fur*ther</if> <sound><wav>far00003.wav</wav></sound> <in><if>far*thest</if> <sound><wav>farthe03.wav</wav></sound>

我需要捕获每一对 &lt;if&gt;...&lt;/if&gt;&lt;wav&gt;...&lt;/wav&gt; 标签。

我的正则表达式是:&lt;if&gt;.*?&lt;\/if&gt;(?:(?!&lt;if&gt;.*?&lt;\/if&gt;).)*?&lt;wav&gt;.*?&lt;\/wav&gt;

Regex101 示例:https://regex101.com/r/eT4wJ9/1

由于某种原因,如果&lt;if&gt;...&lt;/if&gt; 标记出现两次或多次,则此正则表达式匹配从第一次出现开始的所有内容,尽管有负前瞻。为什么会这样?

【问题讨论】:

  • 您不应尝试使用正则表达式处理 XML。 CPAN 上有几个运行良好的 Perl 模块(例如 XML::TwigXML::LibXML,但不要使用 XML::Simple )并使这项任务非常简单,并提供经过测试且更可靠的解决方案。您永远无法确定您没有想过要测试的 XML 数据的微小变化不会破坏您的正则表达式实现。
  • 是的,我知道正则表达式不是解析 HTML 或 XML 的最佳工具,但这是一次性任务,所以我决定试一试。
  • 我不明白。为什么选择错误的工具只是因为它是一次性任务?你是说“我只去附近的商店,所以我会带割草机”吗?

标签: python regex perl


【解决方案1】:

您还需要在 if 块内添加一个负前瞻,这样它就不会匹配嵌套的 if 标记。

<if>(?:(?!</?if>).)*<\/if>(?:(?!<if>.*?<\/if>).)*?<wav>(?:(?!</?wav>).)*<\/wav>

DEMO

示例:

>>> s = '''<in><il>plural</il> <if>aba*cus*es</if> <il>also</il> <if>aba*ci</if> <sound><wav>abaci001.wav</wav><wav>abaci002.wav</wav></sound> <pr>-ˌsaɪ</pr> <altpr>ˈæbəˌsaɪ</altpr></in>
<in><il>plural</il> <if>fau*nas</if> <il>also</il> <if>fau*nae</if> <sound><wav>fauna002.wav</wav></sound> <pr>ˈfɑ:ˌni:</pr></in>
<il>or</il> <if>fur*ther</if> <sound><wav>far00003.wav</wav></sound> <in><if>far*thest</if> <sound><wav>farthe03.wav</wav></sound>'''
>>> for i in re.findall(r'<if>(?:(?!</?if>).)*<\/if>(?:(?!<if>.*?<\/if>).)*?<wav>(?:(?!</?wav>).)*<\/wav>', s):
        print(i)


<if>aba*ci</if> <sound><wav>abaci001.wav</wav>
<if>fau*nae</if> <sound><wav>fauna002.wav</wav>
<if>fur*ther</if> <sound><wav>far00003.wav</wav>
<if>far*thest</if> <sound><wav>farthe03.wav</wav>

【讨论】:

  • .*?&lt;\/if&gt; 是多余的
  • 完美运行。谢谢你,Avinash Raj。
猜你喜欢
  • 2015-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 1970-01-01
  • 2016-08-26
相关资源
最近更新 更多