RegEx删除<p>标签之间的回车</p>

时间:2009-10-22 04:41:53

标签: regex

我一直在努力弄清楚如何删除<p>标签之间发生的回车。 (从技术上讲,我需要用空格替换它们,而不是删除它们。)

这是一个例子。我使用美元符号$作为回车标记。

<p> Ac nec <strong> suspendisse est,dapibus。</strong> Nulla taciti curabitur enim hendrerit。$
Ante ornare phasellus tellus vivamus dictumst dolor aliquam imperdiet lectus。$
Nisl nullam sodales,tincidunt dictum dui eget,gravida anno。 Montes convallis $
adipiscing,aenean hac litora。 Ridiculus,ut consequat curae,amet。诺斯特拉$
phasellus ridiculus class interdum justo。 <em> Pharetra urna est hac </em> laoreet,magna。$
Porttitor purus purus,quis rut​​rum turpis。 Montes netus nibh ornare potential quam $
类。 Natoque nec proin sapien augue curae,elementum。</p>

如示例所示,<p>标记之间可能还有其他标记。所以我正在寻找一个正则表达式来用空格替换所有这些回车但不触及<p>标签之外的任何回车。

非常感谢任何帮助。谢谢!

7 个答案:

答案 0 :(得分:4)

单一正则表达式解决方案在这里基本上是不可能的。如果你绝对坚持不使用HTML解析器,并且你可以指望你的输入格式良好且可预测,那么你可以编写一个简单的词法分析器来完成这项任务(我可以提供示例代码) - 但它仍然没有一个非常好的主意:)

供参考:

答案 1 :(得分:3)

标准答案是:不要尝试使用正则表达式处理HTML(或SGML或XML)。使用适当的解析器。

答案 2 :(得分:2)

正则表达式特别不适合处理“平衡括号”类型的问题,即使人们坚持试图在那里进行欺骗(以及一些实现 - 我正在考虑最近的perl版本,例如 - 尝试通过扩展和扩展“正则表达式”以及超出其CS定义来配合这种广泛的误解; - )。

如果你不需要处理嵌套,它可以通过两遍方法轻松实现 - 用例如<p>.*?</p>(可能带有用于分组的括号),然后在如此标识的每个段落中执行替换。

答案 3 :(得分:1)

[\r\n]+(?=(?:[^<]+|<(?!/?p\b))*</p>)

第一部分与任何类型的行分隔符(\n\r\n\r)中的一个或多个匹配。其余的是前瞻,尝试将所有内容与下一个结束</p>代码匹配,但如果它首先找到一个开始<p>代码,则匹配失败。

请注意,此正则表达式可以非常容易地被欺骗,例如通过SGML注释,<script>元素或普通的格式错误的HTML。此外,我假设您的正则表达式支持正面和负面的前瞻。这些天是一个非常安全的假设,但如果正则表达式不适合你,我们需要确切地知道你正在使用哪种语言或工具。

答案 4 :(得分:0)

只需使用“\n”,但请确保启用多行正则表达式。

答案 5 :(得分:0)

我认为它应该是这样的:

  1. 从teh body获取整段(&lt; p&gt;和&lt; / p&gt;之间的文字)
  2. 创建此段的副本
  3. in copy replace \ n with space
  4. 在身体repace段落中修改了副本
  5. 你可以使用正则表达式来做,但我认为可以使用简单的字符扫描。

    Python中的一些代码:

    rx = re.compile(r'(<p>.*?</p>)', re.IGNORECASE | re.MULTILINE | re.DOTALL)
    
    def get_paragraphs(body):
        paragraphs = []
        body_copy = body
        rxx = rx.search(body_copy)
        while rxx:
            paragraphs.append(rxx.group(1))
            body_copy = body_copy[rxx.end(1):]
            rxx = rx.search(body_copy)
        return paragraphs
    
    def replace_paragraphs(body):
        paragraphs = get_paragraphs(body)
        for par in paragraphs:
            par_new = par.replace('\n', ' ')
            body = body.replace(par, par_new)
        return body
    
    def main():
        new_body = replace_paragraphs(BODY)
        print(new_body)
    
    main() 
    

答案 6 :(得分:0)

这是我在其他答案中承诺的“几乎足够好”的lexing解决方案,用于描述如何做到这一点。它在处理属性方面做出了半心半意的尝试,但并不认真。它也不会尝试应对未编码的“&lt;”在属性中。这些是相对较小的失败,并且它确实处理嵌套的P标签,但是如评论中所述,它完全无法处理某人没有关闭P的情况,因为我们不能这样做没有彻底了解HTML。考虑到 实践仍然存在的普遍性,将此代码声明为“几乎无用”是安全的。 :)

#!/usr/bin/perl
use strict;
use warnings;

while ($html !~ /\G\Z/cg) {
  if ($html =~ /\G(<p[^>]*>)/cg) {
    $output .= $1;
    $in_p ++;
  } elsif ($html =~ m[\G(</p>)]cg) {
    $output .= $1;
    $in_p --; # Woe unto anyone who doesn't provide a closing tag.
    # Tag soup parsers are good for this because they can generate an
    # "artificial" end to the P when they find an element that can't contain
    # a P, or the end of the enclosing element. We're not smart enough for that.
  } elsif ($html =~ /\G([^<]+)/cg) {
    my $text = $1;
    $text =~ s/\s*\n\s*/ /g if $in_p;
    $output .= $text;
  } elsif ($html =~ /\G(<)/cg) {
    $output .= $1;
  } else {
    die "Can't happen, but not having an else is scary!";
  }
}