正则表达式(在PHP中)匹配&这不是HTML实体

时间:2008-11-21 23:47:43

标签: php regex pcre

目标是:用& amp;替换所有独立的&符号。但不能替换那些已经属于HTML实体的人,例如& nbsp;。

我认为我需要一个PHP的正则表达式(最好是preg_函数),它只匹配独立的&符号。我只是不知道如何用preg_replace做到这一点。

5 个答案:

答案 0 :(得分:8)

PHP的htmlentities()对此有double_encode个参数。

如果你想在正则表达式中做类似的事情,那么否定断言就会很有用:

preg_replace('/&(?![a-z#]+;)/i','&',$txt);

答案 1 :(得分:7)

您可以在运行html_entity_decode之前始终运行htmlentities吗?除非您只想做&符号(即使这样你可以使用charset参数),也可以工作。

比正则表达式更容易,更快。

答案 2 :(得分:4)

罗斯让我得到了一个很好的答案。这里的代码似乎运行得相当好。至今。 :-)再次,目标是将HTML转换为XML,特别是RSS提要的描述。在我迄今为止做过的简短测试中(有一些相当古怪的数据)我已经能够将CDATA中的字符串包裹起来并打开它。通过验证测试。谢谢,罗斯。

//decode all entities
$string=html_entity_decode($string,ENT_COMPAT,'UTF-8');

//entity-encode only &<> and double quotes
$string=htmlspecialchars($string,ENT_COMPAT,'UTF-8');

答案 3 :(得分:2)

其他是很好的建议,可能是更好的方法。但我想我会尝试回答问题 - 如果只是提供一个正则表达式的例子。

以下是某些发动机允许的特殊爆炸形式。当然奇怪的是,允许注释正则表达式的引擎允许其他简化的表达 - 但不是通用的。我会在评论中将这些简化的表达式放在parens中。

&                      # an ampersand
( \#                   # a '#' character
  [1-9]                # followed by a non-zero digit, 
  [0-9]{1,3}           # with between 2 and 4             (\d{1,3} or \p{IsDigit}{1,3})
| [A-Za-z]             # OR a letter                      (\p{IsAlpha})
  [0-9A-Za-z]+         # followed by letters or numbers   (\p{IsAlnum}+)
)
;                      # all capped with a ';'

你甚至可以在那里抛出一堆预期的实体,以帮助推出正则表达式扫描程序。

&                      # an ampersand
( amp | apos | gt | lt | nbsp | quot                 
                       # standard entities
| bull | hellip | [lr][ds]quo | [mn]dash | permil          
                       # some fancier ones
| \#                   # a '#' character
  [1-9]                # followed by a non-zero digit, 
  [0-9]{1,3}           # with between 2 and 4 
|  [A-Za-z]            # OR a letter
  [0-9A-Za-z]+         # followed by letters or numbers
)
;                      # all capped with a ';'

答案 4 :(得分:1)

我遇到了同样的问题,最初使用的是:

$string = htmlspecialchars($string, ENT_QUOTES, "UTF-8", FALSE);

但需要它与PHP4和CharSets混合使用,最终得到:


function htmlspecialchars_custom($string)
{
  $string = str_replace("\x05\x06", "", $string);
  $string = preg_replace("/&([a-z\d]{2,7}|#\d{2,5});/i", "\x05\x06$1", $string);
  $string = htmlspecialchars($string, ENT_QUOTES);
  $string = str_replace("\x05\x06", "&", $string);

  return $string;
}

它并不完美,但足以满足我的需求。