正则表达式匹配<content>标记</content>中的每个新行字符(\ n)

时间:2009-07-13 05:19:14

标签: regex

我正在寻找一个正则表达式来匹配\n的XML标记内的每个新行字符(<content>),或者在<content>标记内的任何标记内,例如:

<blog>
<text>
(Do NOT match new lines here)
</text>
<content>
(DO match new lines here)
<p>
(Do match new lines here)
</p>
</content>
(Do NOT match new lines here)
<content>
(DO match new lines here)
</content>

2 个答案:

答案 0 :(得分:71)

实际上......你不能在这里使用简单的正则表达式,至少不能使用一个。您可能需要担心评论!有人可能会写:

<!-- <content> blah </content> -->

您可以采取以下两种方法:

  1. 首先删除所有评论。然后使用正则表达式方法。
  2. 不要使用正则表达式并使用上下文敏感的解析方法来跟踪您是否嵌套在注释中。
  3. 小心。

    我也不确定你能否同时匹配所有新线路。 @Quartz建议这一个:

    <content>([^\n]*\n+)+</content>
    

    这将匹配任何在结束标记之前具有换行符字符的内容标记...但我不确定通过匹配所有换行符的含义。您是否希望能够访问所有匹配的换行符?如果是这样,最好的办法是获取所有内容标记,然后搜索嵌套在其间的所有换行符。更像是这样:

    <content>.*</content>
    

    但是有一个CAVEAT:正则表达式是贪婪的,所以这个正则表达式将匹配第一个开始标记到最后一个结束标记。相反,你必须压制正则表达式,所以它不贪心。在像python这样的语言中,你可以用“?”来做到这一点。正则表达式符号。

    我希望通过这个你可以看到一些陷阱,并弄清楚你想如何继续。您可能最好使用XML解析库,然后迭代所有内容标记。

    我知道我可能不会提供最好的解决方案,但至少我希望你会看到这方面的困难以及为什么其他答案可能不正确......

    更新1:

    让我总结一下,并在我的回复中添加更多细节。我将使用python的正则表达式语法,因为它是我更习惯的(提前原谅我...你可能需要逃避一些字符...评论我的帖子,我会纠正它):

    要删除评论,请使用此正则表达式:      注意“?”抑制。*使其变得非贪婪。

    同样,要搜索内容标记,请使用:     *?

    此外,您可以尝试这一点,并使用匹配对象组()访问每个换行符:

    <content>(.*?(\n))+.*?</content>
    

    我知道我逃脱了,但它抓住了这个主意。最后一个例子可能不起作用,但我认为这是你表达你想要的最好的选择。我的建议仍然是:要么抓住所有内容标签并自己动手,要么使用解析库。

    更新2:

    所以这里是python代码应该工作。我仍然不确定你是什么意思“找到”所有新行。你想要整条线吗?或者只计算新线数。要获得实际行,请尝试:

    #!/usr/bin/python
    
    import re
    
    def FindContentNewlines(xml_text):
        # May want to compile these regexes elsewhere, but I do it here for brevity
        comments = re.compile(r"<!--.*?-->", re.DOTALL)
        content = re.compile(r"<content>(.*?)</content>", re.DOTALL)
        newlines = re.compile(r"^(.*?)$", re.MULTILINE|re.DOTALL)
    
        # strip comments: this actually may not be reliable for "nested comments"
        # How does xml handle <!--  <!-- --> -->. I am not sure. But that COULD
        # be trouble.
        xml_text = re.sub(comments, "", xml_text)
    
        result = []
        all_contents = re.findall(content, xml_text)
        for c in all_contents:
            result.extend(re.findall(newlines, c))
    
        return result
    
    if __name__ == "__main__":
        example = """
    
    <!-- This stuff
    ought to be omitted
    <content>
      omitted
    </content>
    -->
    
    This stuff is good
    <content>
    <p>
      haha!
    </p>
    </content>
    
    This is not found
    """
        print FindContentNewlines(example)
    

    该程序打印结果:

     ['', '<p>', '  haha!', '</p>', '']
    

    第一个和最后一个空字符串来自第一个<p>之前的换行符和</p>之后的换行符。总而言之(大部分)都可以解决这个问题。试用此代码并根据您的需求进行优化。打印中间的东西,这样你就可以看到正则表达式匹配而不匹配。

    希望这会有所帮助: - )。

    PS - 我从第一次更新中尝试我的正则表达式并没有太多运气来捕获所有换行符...如果你这样做,请告诉我。

答案 1 :(得分:4)

<content>(?:[^\n]*(\n+))+</content>