用于查找 HTML 标签及其内容的正则表达式的否定 - java
Negation of regex for finding HTML tags and their content - java
我在 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>
不太了解 Negative Lookahead 以及如何将其应用到我的问题中,所以我将不胜感激任何建议。
您可能想要提取那些您想要在您想要的输出中出现的内容。此表达式可能是更好的选择,如果您愿意,可以对其进行修改:
(<(p|h3.*)>.*<\/(.*)>)|(<(ul.*)>[\s\S]*<\/(ul)>)
它有两组,一组用于p和h3,另一组用于ul,您可以将它们包装到另一个捕获组:
((<(p|h3.*)>.*<\/(.*)>)|(<(ul.*)>[\s\S]*<\/(ul)>))
正则表达式
如果这不是您想要的表达方式,您可以 modify/change 您的表达方式 regex101.com。
正则表达式电路
您还可以在 jex.im:
中可视化您的表情
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));
}
}
Java脚本演示
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}`);
});
}
此表达式可能只会捕获您想要的输出。它不遵循否定策略。
您尝试使用的负面展望需要写成 (?!(?:h3|ul|p)\b)
,它不会 select h3
或 ul
或 p
标签。注意在它后面使用单词边界 \b
以拒绝那些标签的精确匹配。除了删除这些标签之外,您还必须删除删除这些标签后留下的白色spaces,因此总体而言,您需要使用的正则表达式是这样的,
\h*<(?!(?:h3|ul|p)\b)([^>]+).*?>[\w\W]*?</>\s*
正则表达式解释:
\h*
- 在标签 之前匹配零个或多个水平白色space(space和制表符,可能是其他存在的)
<
- 标签开始
(?!(?:h3|ul|p)\b)
- 否定前瞻以准确拒绝 h3
ul
和 p
标签
([^>]+)
- 匹配标签名称一个或多个字符并在 group1 中捕获以供稍后反向引用。您可以使用 \w+
之类的东西或包含允许字符的字符集来仅匹配您想要的内容。
.*?>
- 可选择匹配零个或多个字符(基本属性),然后用 >
结束开始标记
[\w\W]*?
- 以 non-greedy 方式 匹配零个或多个字符,包括换行符
</>
- 匹配标签的结尾,其中 </code> 表示之前匹配的标签名称 </li>
<li><code>\s*
- 匹配零个或多个白色space,它基本上消耗了通过删除标签 创建的空space
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>
我在 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>
不太了解 Negative Lookahead 以及如何将其应用到我的问题中,所以我将不胜感激任何建议。
您可能想要提取那些您想要在您想要的输出中出现的内容。此表达式可能是更好的选择,如果您愿意,可以对其进行修改:
(<(p|h3.*)>.*<\/(.*)>)|(<(ul.*)>[\s\S]*<\/(ul)>)
它有两组,一组用于p和h3,另一组用于ul,您可以将它们包装到另一个捕获组:
((<(p|h3.*)>.*<\/(.*)>)|(<(ul.*)>[\s\S]*<\/(ul)>))
正则表达式
如果这不是您想要的表达方式,您可以 modify/change 您的表达方式 regex101.com。
正则表达式电路
您还可以在 jex.im:
中可视化您的表情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));
}
}
Java脚本演示
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}`);
});
}
此表达式可能只会捕获您想要的输出。它不遵循否定策略。
您尝试使用的负面展望需要写成 (?!(?:h3|ul|p)\b)
,它不会 select h3
或 ul
或 p
标签。注意在它后面使用单词边界 \b
以拒绝那些标签的精确匹配。除了删除这些标签之外,您还必须删除删除这些标签后留下的白色spaces,因此总体而言,您需要使用的正则表达式是这样的,
\h*<(?!(?:h3|ul|p)\b)([^>]+).*?>[\w\W]*?</>\s*
正则表达式解释:
\h*
- 在标签 之前匹配零个或多个水平白色space(space和制表符,可能是其他存在的)
<
- 标签开始(?!(?:h3|ul|p)\b)
- 否定前瞻以准确拒绝h3
ul
和p
标签([^>]+)
- 匹配标签名称一个或多个字符并在 group1 中捕获以供稍后反向引用。您可以使用\w+
之类的东西或包含允许字符的字符集来仅匹配您想要的内容。.*?>
- 可选择匹配零个或多个字符(基本属性),然后用>
结束开始标记
[\w\W]*?
- 以 non-greedy 方式 匹配零个或多个字符,包括换行符
</>
- 匹配标签的结尾,其中</code> 表示之前匹配的标签名称 </li> <li><code>\s*
- 匹配零个或多个白色space,它基本上消耗了通过删除标签 创建的空space
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>