【问题标题】:regex (in PHP) to match & that aren't HTML entities正则表达式(在 PHP 中)匹配 & 不是 HTML 实体
【发布时间】:2010-09-23 13:25:25
【问题描述】:

我们的目标是:用 & 替换所有独立的 & 符号。但不能替换那些已经属于 HTML 实体的部分,例如  。

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

【问题讨论】:

    标签: php regex pcre


    【解决方案1】:

    您总是可以在运行htmlentities 之前运行html_entity_decode?除非你只想做 & 符号(即使那样你也可以使用字符集参数)。

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

    【讨论】:

    • 我可能应该解释一下总体目标。我有 UTF-8 的字符串,并且 可能 有 HTML 实体。我想在 UTF-8 RSS 提要的描述元素中使用它们。据我所知,RSS/XML 接受十六进制 HTML 实体,但很少或不接受字母数字实体。
    • 使用 Atom 代替 RSS - 实体没有问题 :)
    【解决方案2】:

    Ross 让我得到了一个很好的答案。这是似乎运行良好的代码。迄今为止。 :-) 同样,目标是将 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】:

      其他的都是很好的建议,可能是更好的方法。但我想我会尝试按要求回答这个问题——如果只是为了提供一个正则表达式示例。

      以下是某些引擎中允许的特殊分解形式。当然,奇怪的是允许注释正则表达式的引擎允许其他简化表达式 - 但不是通用的。我会将这些简化的表达式放在 cmets 中的括号中。

      &                      # 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 ';'
      

      【讨论】:

      • 你也可以有' '类型,因此您需要再添加一个分支,但在实际说明正则表达式时很好。
      • 虽然您匹配的是 HTML 实体而不是不属于实体的“&”。
      【解决方案4】:

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

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

      preg_replace('/&(?!(?:[[:alpha:]][[:alnum:]]*|#(?:[[:digit:]]+|[Xx][[:xdigit:]]+));)/', '&amp;', $txt);
      

      【讨论】:

        【解决方案5】:

        我也遇到了同样的问题,原来是用的:

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

        但需要它与 PHP4 和混合字符集一起使用,最终得到:

        
        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;
        }
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-06
          • 2011-02-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多