2

我有一个带有一些标记的字符串,如下所示:

The quick brown <a href="www.fox.org">fox</a> jumped over the lazy <a href="entry://id=6000009">dog</a> <img src="dog.png" />.

我正在尝试剥离除内部带有“entry://id=”的锚元素之外的所有内容。因此,上述示例的所需输出将是:

The quick brown fox jumped over the lazy <a href="entry://id=6000009">dog</a>.

写这场比赛,到目前为止我最接近的是:

<.*?>!<a href=\"entry://id=\\d+\">.*?<\\/a>

但我不明白为什么这不起作用。任何帮助(除了“你为什么不使用解析器”:) 将不胜感激!

4

3 回答 3

7

我真的不会使用正则表达式来解析 HTML。HTML 是不规则的,并且没有结束的边缘情况让你绊倒。

改为查看JTidy 。

于 2009-08-20T12:36:09.853 回答
1

使用正则表达式不容易。我推荐一个理解 HTML/XML 语义的解析器。

如果你坚持,你可以做一个多步骤的方法,比如:

  • 替换"<(a\s*href="entry:.*?/a)>""{{{{\1}}}}"
  • 替换"<(?!/a}}}})[^>]*>"""
  • 替换"{{{{""<"
  • 替换"}}}}"">"

请注意,上述内容容易出错,并且在某些时候会失败。认为它是一个丑陋的黑客,而不是一个真正的解决方案。对于在正则表达式感知的文本编辑器中一次性编辑某些文本文件来说,上述内容是可以的,但对于在应用程序中作为数据处理的一部分重复的、真实的使用 - 不是那么多。

于 2009-08-20T12:44:50.777 回答
1

使用这个:

((<a href="entry://id=\d+">.*?</a>)|<!\[CDATA\[.*?\]\]>|<!--.*?-->|<.*?>)

并将其与 replace all $2 结合起来适用于您的示例。下面的代码证明了这一点:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.junit.Assert.*;
import org.junit.Test;


public class TestStack1305864 {

    @Test
    public void matcherWithCdataAndComments(){
        String s="The quick <span>brown</span> <a href=\"www.fox.org\">fox</a> jumped over the lazy <![CDATA[ > ]]> <a href=\"entry://id=6000009\">dog</a> <img src=\"dog.png\" />.";
        String r="The quick brown fox jumped over the lazy <a href=\"entry://id=6000009\">dog</a> .";
        String pattern="((<a href=\"entry://id=\\d+\">.*?</a>)|<!\\[CDATA\\[.*?\\]\\]>|<!--.*?-->|<.*?>)";
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(s);

        String t = s.replaceAll(pattern, "$2");
        System.out.println(t);
        System.out.println(r);
        assertEquals(r, t);
    }
}

这个想法是捕获您有兴趣保留在特定组中的所有元素,以便您可以将它们插入回字符串中。
这样你就可以全部替换:
对于每个与有趣元素不匹配的元素,组将为空,元素将被替换为 ""
对于有趣的元素,组不会为空,并将附加到结果字符串.

编辑:在 CDATA 和注释中处理嵌套的 < 或 >
编辑:请参阅http://martinfowler.com/bliki/ComposedRegex.html了解正则表达式组合模式,旨在使正则表达式更具可读性以用于维护目的。

于 2009-08-20T13:37:32.437 回答