为什么正则表达式只在其他人出现时才匹配字符串?

时间:2014-01-03 15:06:16

标签: java regex

我有一个HTML结束标记的白名单(brbidiv): -

String whitelist = "([^br|^b|^i|^div])";
String endTagPattern = "(<[ ]*/[ ]*)" + whitelist + "(>?).*?([^>]+>)";
...
html = html.replaceAll(endTagPattern, "[r]");

我的测试String会移除那些不在白名单中的人的结束标记,在这种情况下,为了清楚起见,将其替换为[r]: -

1. <b>bold</b>, 2. <i>italic</i>, 3. <strong>strong</strong>, 4. <div>div</div>, 5. <script lang='test'>script</script>
1. <b>bold</b>, 2. <i>italic</i>, 3. <strong>strong[r], 4. <div>div</div>, 5. <script lang='test'>script[r]

如果我将strong添加到此白名单

String whitelist = "([^br|^b|^i|^div|^strong])";

它不仅与strong结束标记不匹配,还会停止匹配结束script标记或其他任何标记。

我的问题是,为什么?

2 个答案:

答案 0 :(得分:4)

原因是你正在使用一个字符类。在字符类中,除了处理字符范围外,字符的顺序并不重要。

因此,[^br|^b|^i|^div|^strong]实际上将匹配除以下字符之外的任何字符:

bridvstrong|^

[请注意|^也是如此。

您可以使用[^bridvstrong|^]并且行为方式相同。

你可能会看一下负向前瞻。

答案 1 :(得分:1)

String whitelist = "([^br|^b|^i|^div])";

使用[]创建一个字符类。我认为你写了这个,所以你可以使用^作为“not”,但是字符类在这里是不合适的。在方括号内,|并不代表“或”;它只是一个文字管道角色。撰写div div不匹配,它会匹配三个字符之一,di或{{1 }}。否定这意味着“匹配除vdi之外的所有内容。

该白名单实际上等同于v - 它匹配的单个字符不是[^bdirv|\^]bdi,{{1 }},rv

|

如果您想排除某些匹配项,您需要的是negative lookahead。如果没有方括号,您可以按照预期的方式使用^作为“或”运算符。