我在PHP中开发Telegram Bot,我必须处理只有Edgar F. Codd和所有<
,>
和&
符号的字符串不是标记的一部分,HTML实体必须替换为相应的HTML实体(<
<
,>
>
和&
&
)
示例字符串
<b>bold</b>, <strong>bold</strong>
<i>italic</i>, <em>italic</em>
<a href="http://www.example.com/" >inline URL</a>
<code>inline fixed-width code</code>
<pre>pre-formatted fixed-width code block</pre>
yes<b bad<>b> <bad& hi>;<strong >b<a<
我设法使用Regex替换&
和<
。例如,我在此模式<(?!(?:(?:\/?)(?:(?:b>)|(?:strong>)|(?:i>)|(?:em>)|(?:code>)|(?:pre>)|(?:a(?:[^>]+?)?>))))
中使用否定前瞻来摆脱<
符号。
但是我无法构建模式来替换不属于任何标记的>
符号。 PCRE不支持无限量词。虽然它允许外观内部的替代品具有不同的长度,但要求每个替代品具有固定的长度。
所以,我尝试使用这种模式(仍然不完整)(?<!(?:(?:<b)|(?:<strong)|(?:<i)|(?:<em)|(?:<code)|(?:<pre>)|(?:<a)))>
,其中所有替代品都有固定的长度,但它仍然说Compilation failed: lookbehind assertion is not fixed length
答案 0 :(得分:1)
正确的答案是使用DOM解析器。对于快速而肮脏(有时更快)的方法,您可以使用(*SKIP)(*FAIL)
实现的PCRE
机制:
<[^<>&]+>(*SKIP)(*FAIL)|[<>&]+
<小时/>
完整的PHP
演练将是:
<?php
$string = <<<DATA
<b>bold</b>, <strong>bold</strong>
<i>italic</i>, <em>italic</em>
<a href="http://www.example.com/" >inline URL</a>
<code>inline fixed-width code</code>
<pre>pre-formatted fixed-width code block</pre>
yes<b bad<>b> <bad& hi>;<strong >b<a<
DATA;
$regex = '~<[^<>&]+>(*SKIP)(*FAIL)|[<>&]+~';
$string = preg_replace_callback($regex,
function($match) {
return htmlentities($match[0]);
},
$string);
echo $string;
?>
哪个收益率:
<b>bold</b>, <strong>bold</strong>
<i>italic</i>, <em>italic</em>
<a href="http://www.example.com/" >inline URL</a>
<code>inline fixed-width code</code>
<pre>pre-formatted fixed-width code block</pre>
yes<b bad<>b> <bad& hi>;<strong >b<a<
然而,正如之前在StackOverflow上多次提到的那样,考虑使用解析器,而不是之后的所有内容。
<小时/> 解析器方式可以是:
$dom = new DOMDocument();
$dom->loadHTML($string, LIBXML_HTML_NOIMPLIED | LIBXML_NOERROR);
echo $dom->saveHTML();
但是,您呈现的代码段已损坏,因此正则表达式可能是处理它的唯一方法。
答案 1 :(得分:1)
您可以找到要转换为此类实体的合法特殊符号。
最重要的是正确解析标签 免责声明 - 如果您不按照以下方式执行操作,则没有理由使用正则表达式,它将无效。
在每场比赛中,组0将包含&lt;,&gt;或&amp;
您可以添加更多内容,请参阅底部的正则表达式
正则表达式
(?:(?><(?:(?:(?:(script|style|object|embed|applet|noframes|noscript|noembed)(?:\s+(?>"[\S\s]*?"|'[\S\s]*?'|(?:(?!/>)[^>])?)+)?\s*>)[\S\s]*?</\1\s*(?=>))|(?:/?[\w:]+\s*/?)|(?:[\w:]+\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]?)+\s*/?)|\?[\S\s]*?\?|(?:!(?:(?:DOCTYPE[\S\s]*?)|(?:\[CDATA\[[\S\s]*?\]\])|(?:--[\S\s]*?--)|(?:ATTLIST[\S\s]*?)|(?:ENTITY[\S\s]*?)|(?:ELEMENT[\S\s]*?))))>)(*SKIP)(*FAIL)|[<>]|[&](?!(?i:[a-z]+|(?:\#(?:[0-9]+|x[0-9a-f]+)));))
解释
(?:
(?> # Atomic group
< # Match tag forms and fail them with skip / fail verbs ( see below )
(?:
(?:
(?:
# Invisible content; end tag req'd
( # (1 start)
script
| style
#| head
| object
| embed
| applet
| noframes
| noscript
| noembed
) # (1 end)
(?:
\s+
(?>
" [\S\s]*? "
| ' [\S\s]*? '
| (?:
(?! /> )
[^>]
)?
)+
)?
\s* >
)
[\S\s]*? </ \1 \s*
(?= > )
)
| (?: /? [\w:]+ \s* /? )
| (?:
[\w:]+
\s+
(?:
" [\S\s]*? "
| ' [\S\s]*? '
| [^>]?
)+
\s* /?
)
| \? [\S\s]*? \?
| (?:
!
(?:
(?: DOCTYPE [\S\s]*? )
| (?: \[CDATA\[ [\S\s]*? \]\] )
| (?: -- [\S\s]*? -- )
| (?: ATTLIST [\S\s]*? )
| (?: ENTITY [\S\s]*? )
| (?: ELEMENT [\S\s]*? )
)
)
)
>
) # End atomic group
(*SKIP)(*FAIL)
| #or,
[<>] # Angle brackets
| #or,
[&] # Ampersand
(?! # Only if not an entity
(?i:
[a-z]+
| (?:
\#
(?:
[0-9]+
| x [0-9a-f]+
)
)
)
;
)
# Add more here
)