使用CodeIgniter的正则表达式缩小最终的HTML输出

Ama*_*man 16 php regex compression codeigniter

Google页面建议您缩小HTML,即删除所有不必要的空格. CodeIgniter确实具有giziping输出的功能,或者可以通过.htaccess.但我仍然想从最终的HTML输出中删除不必要的空格.

我用这段代码玩了一下,看起来很有效.这确实导致HTML没有多余空格并删除其他选项卡格式.

class Welcome extends CI_Controller 
{
    function _output()
    {
        echo preg_replace('!\s+!', ' ', $output);
    }

    function index(){
    ...
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是可能有像<pre>,<textarea>等等的标签 ,其中可能有空格,正则表达式应该删除它们.那么,如何从最终的HTML中删除多余的空间,而不使用正则表达式影响这些特定标记的空格或格式?

感谢@Alan Moore得到了答案,这对我有用

echo preg_replace('#(?ix)(?>[^\S ]\s*|\s{2,})(?=(?:(?:[^<]++|<(?!/?(?:textarea|pre)\b))*+)(?:<(?>textarea|pre)\b|\z))#', ' ', $output);
Run Code Online (Sandbox Code Playgroud)

ridgerunner在分析这个正则表达方面做得很好.我最终使用了他的解决方案.干杯里的干杯.

rid*_*ner 49

对于那些对艾伦·摩尔的正则表达式如何运作感兴趣的人(是的,它确实有效),我冒昧地评论它,以便它可以被凡人阅读:

function process_data_alan($text) // 
{
    $re = '%# Collapse ws everywhere but in blacklisted elements.
        (?>             # Match all whitespans other than single space.
          [^\S ]\s*     # Either one [\t\r\n\f\v] and zero or more ws,
        | \s{2,}        # or two or more consecutive-any-whitespace.
        ) # Note: The remaining regex consumes no text at all...
        (?=             # Ensure we are not in a blacklist tag.
          (?:           # Begin (unnecessary) group.
            (?:         # Zero or more of...
              [^<]++    # Either one or more non-"<"
            | <         # or a < starting a non-blacklist tag.
              (?!/?(?:textarea|pre)\b)
            )*+         # (This could be "unroll-the-loop"ified.)
          )             # End (unnecessary) group.
          (?:           # Begin alternation group.
            <           # Either a blacklist start tag.
            (?>textarea|pre)\b
          | \z          # or end of file.
          )             # End alternation group.
        )  # If we made it here, we are not in a blacklist tag.
        %ix';
    $text = preg_replace($re, " ", $text);
    return $text;
}
Run Code Online (Sandbox Code Playgroud)

我是新来的,但是我可以看到Alan非常擅长正则表达式.我只会添加以下建议.

  1. 有一个不必要的捕获组可以删除.
  2. 虽然OP没有这么说,该<SCRIPT>元素应该被添加到<PRE><TEXTAREA>黑名单.
  3. 添加'S'PCRE"study"修饰符可将此正则表达式加速约20%.
  4. 前瞻中有一个交替组,适用于应用Friedl的" 展开循环 "效率结构.
  5. 更严重的是,这个相同的交替组:(即(?:[^<]++|<(?!/?(?:textarea|pre)\b))*+)容易受到大型目标字符串上的过多PCRE递归的影响,这可能导致堆栈溢出导致Apache/PHP可执行文件无声地发生故障并且在没有警告的情况下崩溃.(Apache的Win32版本httpd.exe特别容易受到影响,因为与*nix可执行文件相比,它只有256KB的堆栈,通常使用8MB或更多堆栈构建.)Philip Hazel(PHP中使用的PCRE正则表达式引擎的作者)讨论文档中的这个问题:PCRE讨论堆栈使用.尽管Alan已经正确应用了与Philip在本文档中显示的相同的修复(对第一个替代品应用了占有性加),但如果HTML文件很大并且有很多非黑名单标签,那么仍会有很多递归.例如,在我的Win32盒子上(具有256KB堆栈的可执行文件),脚本会爆炸,测试文件只有60KB.另请注意,PHP不遵循建议并将默认递归限制设置为过高100000.(根据PCRE文档,这应该设置为等于堆栈大小除以500的值).

这是一个改进的版本,比原版更快,处理更大的输入,如果输入字符串太大而无法处理,则优雅地失败并显示消息:

// Set PCRE recursion limit to sane value = STACKSIZE / 500
// ini_set("pcre.recursion_limit", "524"); // 256KB stack. Win32 Apache
ini_set("pcre.recursion_limit", "16777");  // 8MB stack. *nix
function process_data_jmr1($text) // 
{
    $re = '%# Collapse whitespace everywhere but in blacklisted elements.
        (?>             # Match all whitespans other than single space.
          [^\S ]\s*     # Either one [\t\r\n\f\v] and zero or more ws,
        | \s{2,}        # or two or more consecutive-any-whitespace.
        ) # Note: The remaining regex consumes no text at all...
        (?=             # Ensure we are not in a blacklist tag.
          [^<]*+        # Either zero or more non-"<" {normal*}
          (?:           # Begin {(special normal*)*} construct
            <           # or a < starting a non-blacklist tag.
            (?!/?(?:textarea|pre|script)\b)
            [^<]*+      # more non-"<" {normal*}
          )*+           # Finish "unrolling-the-loop"
          (?:           # Begin alternation group.
            <           # Either a blacklist start tag.
            (?>textarea|pre|script)\b
          | \z          # or end of file.
          )             # End alternation group.
        )  # If we made it here, we are not in a blacklist tag.
        %Six';
    $text = preg_replace($re, " ", $text);
    if ($text === null) exit("PCRE Error! File too big.\n");
    return $text;
}
Run Code Online (Sandbox Code Playgroud)

ps我非常熟悉这个PHP/Apache seg-fault问题,因为我在帮助Drupal社区时正在努力解决这个问题.请参阅:优化CSS选项导致php cgi在pcre函数"match"中发生段错误.我们还通过FluxBB论坛软件项目中的BBCode解析器体验了这一点.

希望这可以帮助.

  • @william - "渲染"?错误324来自什么 - `httpd.exe`?`php.exe`?需要更多信息才能继续.首先尝试将`pcre.recursion_limit`设置为524(脚本当前将其设置为16777).只需注释掉一行并取消注释另一行. (2认同)