用于查找HTML标签及其内容的正则表达式的取反-Java

时间:2019-05-15 17:13:25

标签: java html regex regex-negation

我正在uni上做一个项目,我必须使用正则表达式清理一些HTML代码(我知道,这不是最好的方法...)

正文输入:

<h1>This is heading 1</h1>
<h2 style="color: aqua">This is heading 2</h2>
<h3>This is heading 3</h3>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
<a href="https://www.w3schools.com">This is a link</a>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

我得到了允许标签的列表,我还必须删除所有其他标签及其内容。例如{h3, p, ul}

首先我剥离所有参数(不允许使用),然后提出这个正则表达式,该正则表达式会删除标签和内容。

String regex = "(?i)<([h3|ul|p]+)>\\n?.*\\n?<\\/\\1>";

它可以工作,但是现在我必须对其进行否定并删除所有标签和内容(除了...中给出的那些标签和内容)。

我尝试了这个,但是不起作用:

`...[?!h3|ul|p]...`

此示例的预期结果:

<h3>This is heading 3</h3>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
<ul>
</ul>

不太了解负向超前以及如何将其应用于我的问题,因此,我将感谢您的任何建议。

2 个答案:

答案 0 :(得分:1)

您可能想要提取想要出现在所需输出中的那些内容。如果需要,此表达式可能是一个更好的选择,可以对其进行修改:

(<(p|h3.*)>.*<\/(.*)>)|(<(ul.*)>[\s\S]*<\/(ul)>)

它有两组,一组用于p和h3,另一组用于ul,您可以将它们包装到另一个捕获组:

((<(p|h3.*)>.*<\/(.*)>)|(<(ul.*)>[\s\S]*<\/(ul)>))

RegEx

如果这不是您想要的表达式,则可以在regex101.com中修改/更改表达式。

enter image description here

RegEx电路

您还可以在jex.im中可视化您的表达式:

enter image description here

Java测试

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

final String regex = "((<(p|h3.*)>.*<\\/(.*)>)|(<(ul.*)>[\\s\\S]*<\\/(ul)>))";
final String string = "<h1>This is heading 1</h1>\n"
     + "<h2 style=\"color: aqua\">This is heading 2</h2>\n"
     + "<h3>This is heading 3</h3>\n"
     + "<p>This is a paragraph.</p>\n"
     + "<p>This is another paragraph.</p>\n"
     + "<a href=\"https://www.w3schools.com\">This is a link</a>\n"
     + "<ul>\n"
     + "  <li>Coffee</li>\n"
     + "  <li>Tea</li>\n"
     + "  <li>Milk</li>\n"
     + "</ul>";

final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);

while (matcher.find()) {
    System.out.println("Full match: " + matcher.group(0));
    for (int i = 1; i <= matcher.groupCount(); i++) {
        System.out.println("Group " + i + ": " + matcher.group(i));
    }
}

JavaScript演示

const regex = /((<(p|h3.*)>.*<\/(.*)>)|(<(ul.*)>[\s\S]*<\/(ul)>))/gm;
const str = `<h1>This is heading 1</h1>
<h2 style="color: aqua">This is heading 2</h2>
<h3>This is heading 3</h3>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
<a href="https://www.w3schools.com">This is a link</a>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

此表达式可能仅捕获您所需的输出。它不遵循否定策略。

答案 1 :(得分:1)

您要使用的负面外观必须写成(?!(?:h3|ul|p)\b),它不会选择h3ulp标签。请注意,在其后使用单词边界\b可以拒绝这些标签的精确匹配。除了删除这些标签之外,您还必须删除在删除这些标签后留下的空白,因此总体上您需要使用的正则表达式是

\h*<(?!(?:h3|ul|p)\b)([^>]+).*?>[\w\W]*?</\1>\s*

正则表达式说明

  • \h*-在标记之前匹配零个或多个水平空白(空格和制表符,可能还有其他空格)
  • <-标记的开头
  • (?!(?:h3|ul|p)\b)-负向查找以完全拒绝h3 ulp标签
  • ([^>]+)-匹配标签名称一个或多个字符,并捕获到group1中以供以后反向引用。您可以使用类似\w+之类的字符或具有允许的字符的字符集来仅匹配您想要的字符。
  • .*?>-(可选)匹配零个或多个字符(基本上是属性),然后用>关闭起始标签
  • [\w\W]*?-以非贪婪的方式匹配零个或多个字符,包括换行符
  • </\1>-匹配标签的结尾,其中\1代表之前匹配的标签名称
  • \s*-匹配零个或多个空白,这些空白基本上消耗了通过删除标记创建的空白空间

Regex Demo

Java代码演示

String s = "<h1>This is heading 1</h1>\r\n" + 
        "<h2 style=\"color: aqua\">This is heading 2</h2>\r\n" + 
        "<h3>This is heading 3</h3>\r\n" + 
        "<p>This is a paragraph.</p>\r\n" + 
        "<p>This is another paragraph.</p>\r\n" + 
        "<a href=\"https://www.w3schools.com\">This is a link</a>\r\n" + 
        "<ul>\r\n" + 
        "  <li>Coffee</li>\r\n" + 
        "  <li>Tea</li>\r\n" + 
        "  <li>Milk</li>\r\n" + 
        "</ul>";

System.out.println("Before:\n" + s);
System.out.println("\nAfter:\n" + s.replaceAll("\\h*<(?!(?:h3|ul|p)\\b)([^>]+).*?>[\\w\\W]*?</\\1>\\s*", ""));

输出

Before:
<h1>This is heading 1</h1>
<h2 style="color: aqua">This is heading 2</h2>
<h3>This is heading 3</h3>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
<a href="https://www.w3schools.com">This is a link</a>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

After:
<h3>This is heading 3</h3>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
<ul>
</ul>