我使用strip_tags来确保在保存字符串之前删除每个HTML标记。现在我得到了一个问题,没有任何结束标签的单个<
也被删除了。现在的想法是用匹配的HTML实体<
替换每一个<
,我得到了一个正则表达式,但它只替换了第一个find,有什么想法吗?
这是我现在得到的正则表达式:preg_replace("/<([^>]*(<|$))/", "<$1", $string);
我想要这个
<p> Hello < 30 </p> < < < <!-- Test --> <> > > >
成为preg_replace(REGEX, REPLACE, $string)
的第一个:
<p> Hello < 30 </p> < < < <!-- Test --> <> > > >
然后在strip_tags($string)
之后:
Hello < 30 < < < <> > > >
你知道我该怎么做吗?
也许你知道一个更好的方法。
1条答案
按热度按时间dfuffjeb1#
你的问题很有趣,所以我花时间尝试解决它。我认为唯一的方法是分几步来做:
1.第一步是删除HTML注解。
1.下一步是尝试将所有HTML标记与正则表达式匹配,以便将它们重写为另一种形式,将
<
和>
字符替换为其他字符,例如[[
和]]
。1.之后,您可以将
<
替换为<
,将>
替换为>
。1.我们将
[[tag attr="value"]]
和[[/tag]]
替换为原始的HTML标记<tag attr="value">
和</tag>
。1.我们现在可以使用
strip_tags()
或更安全、更灵活的库(如HTMLPurifier)来剥离我们想要的HTML标记。PHP代码
抱歉,但颜色突出显示似乎是错误的,因为我使用Nowdoc字符串来方便编辑:
你可以在这里运行:https://onlinephp.io/c/005a3
对于正则表达式,我使用
~
而不是通常的/
来分隔模式和标志。这只是因为我们可以在模式中使用斜杠而不用转义它。我还使用了
x
标志作为extended表示法,这样我就可以在我的模式中添加一些注解,并将其写在几行中。为了可读性和灵活性,我还使用了命名的捕获组,如
(?<quote>)
,这样我们就没有索引,如果我们添加一些其他捕获组,索引可能会移动。使用\k<quote>
而不是索引版本\4
进行反向引用。HTML5似乎相当宽容,因为似乎可以将
>
char放入属性值中,而无需将其替换为>
。我想这在过去是不允许的,它变成了“ok/accepted”,以帮助用户在<input>
字段上写入可读的pattern
属性。我添加了一个密码字段的示例,其中不允许使用<
和>
字符。这是为了展示如何在正则表达式中处理它,通过接受带有单引号或双引号值的属性。输出:
正如您所看到的,
strip_tags()
没有处理标记名周围的空格,我发现这完全不安全!这就是为什么我建议使用HTMLPurifier或DOM解析器之类的库。