<?php
ini_set('pcre.backtrack_limit', 10000000);
$content = '22222';
$bad_words = "/000|22222|33333|4月25日|44444|66666|77777|81813|88888|99999|555555|恐怖/i";
if(preg_match ($bad_words, $content)) {
echo 'exists';
} else {
echo 'not exists';
}
?>
如上程序,$bad_words内容少时,程序正常,但内容很长的时候,就会报错了:
Warning: preg_match() [function.preg-match]: Compilation failed: regular expression is too large at offset 39505 in D:\www\htdocs\1.php on line 5
not exists

解决方案 »

  1.   

    多长时会报错?可以用strpos 来验证或者将过滤词放入数组中再来验证
      

  2.   

    修改php.ini加入一句:pcre.backtrack_limit=-1即可  记得重启apache 
      

  3.   

    再多能有多少。实现这个功能,还用得着ini_set('pcre.backtrack_limit'这个么!
    我有个现成的,参考一下:
    其中badword.txt是过滤词汇集合,一词一行//过滤内容
    function filter($text) {
      //这里写其它处理的代码
      filter_badwords($text);
      return $text;
    }
    //过滤词汇
    function filter_badwords($text) {
      if ($badwords = @file('badword.txt')) {
        foreach ($badwords as $badword) {
      $badword = trim($badword);
      if ($badword != '') {
            $badword = preg_replace('/[0-9a-z]|[\x80-\xff]{3}/iU', '$0([^0-9a-z\x80-\xff]|(&[#a-z0-9]+;)| )*', $badword);
            $badword = preg_replace('/\(\[\^0-9a-z\\\x80-\\\xff\]\|\(&\[#a-z0-9\]\+;\)\| \)\*$/i', '', $badword);
            $badword = preg_replace('/^\(\[\^0-9a-z\\\x80-\\\xff\]\|\(\&\[\#a-z0-9\]\+\;\)\| \)\*/i', '', $badword);
            if (preg_match('/'.$badword.'/i', $text, $matches))
              die('提交被拒绝!有禁用词汇“'.preg_replace('/[0-9a-z]|[\x80-\xff]{3}/iU', '$0<span style="color:#FFFFFF;display:none;">禁</span>', $matches[0]).'”。请返回检查。');
            unset($matches);
          }
        }
      }
    }
      

  4.   


    <?php
    //过滤内容
    function filter($text) {
      //这里写其它处理的代码
      filter_badwords($text);
      return $text;
    }
     
     
    //过滤词汇
    function filter_badwords($text) {
      if ($badwords = @file('badword.txt')) {
        foreach ($badwords as $badword) {
          $badword = trim($badword);
          if ($badword != '') {
            $badword = preg_replace('/[0-9a-z]|[\x80-\xff]{3}/iU', '$0([^0-9a-z\x80-\xff]|(&[#a-z0-9]+;)| )*', $badword);
            $badword = preg_replace('/\(\[\^0-9a-z\\\x80-\\\xff\]\|\(&\[#a-z0-9\]\+;\)\| \)\*$/i', '', $badword);
            $badword = preg_replace('/^\(\[\^0-9a-z\\\x80-\\\xff\]\|\(\&\[\#a-z0-9\]\+\;\)\| \)\*/i', '', $badword);
            if (preg_match('/'.$badword.'/i', $text, $matches))
              die('提交被拒绝!有禁用词汇"'.preg_replace('/[0-9a-z]|[\x80-\xff]{3}/iU', '$0<span style="color:#FFFFFF;display:none;">禁</span>', $matches[0]).'"。请返回检查。');
            unset($matches);
          }
        }
      }
    }
    filter_badwords('5dd399');
    ?>同样超出了:
    Warning: preg_match() [function.preg-match]: Compilation failed: missing terminating ] for character class at offset 46 in D:\www\htdocs\temp.php on line 42
      

  5.   

    补充:上面的语句:badword.txt,大小24,5K
      

  6.   

    一个一个的来,说到banword ,我用的是scws 来验证的。
       $text = @iconv("utf-8", "gbk", $text);
            $so = scws_new();
            $dicPath = self::INC_TEXT_DIR . self::BANNDED_WORD;
            $so->set_dict($dicPath, SCWS_XDICT_TXT);
            $so->send_text($text);
            $text = @iconv("gbk", "utf-8", $text);
            $ret = $so->has_word("*");
            if ($ret) {
                $result = $so->get_words("*");
                $words = array();
                foreach ($result as $w) {
                    $words[] = $w['word'];
                }
                $message = '含有敏感词:' . iconv('gb2312', 'utf-8', implode(',', $words)) . ' 请用下划线_隔开敏感词';
                KDG::log("step2.1.1 关健字审核  <font color='red'> $message </font> <font color='red'> 发送文字合法性验证未通过,发送短信关闭</font>");
                return array(false, $message);
            }
      

  7.   

    1有完整的代码没,发过来我试试。我看到你的效果第二次像是语法报错,不像是长度超出了。
    2建议多打开几个。    ini_set("pcre.backtrack_limit" , -1);
        ini_set("pcre.recursion_limit" , -1);
        ini_set("memory_limit" , "1024M");
      

  8.   

    备注一下,我用的scws 的banword.txt 大小为33 k,运行很正常。
    如果程序赶着做,就建议先用scws 做分词验证。
    如果有时间慢慢研究,就好好看看正则配置的问题。我之前有一次做采集,也有类似的限制,改改配置后就正常了。
      

  9.   

    完整代码如下:$bad_words如果是下面那么少,就正常,如果自己多复制些,就会报错:
    <?php
    ini_set("pcre.backtrack_limit" , -1);
    ini_set("pcre.recursion_limit" , -1);
    ini_set("memory_limit" , "1024M");
    $content = '22222';
    $bad_words = "/000|22222|33333|4月25日|44444|66666|77777|81813|88888|99999|555555|恐怖/i";
    if(preg_match ($bad_words, $content)) {
        echo 'exists';
    } else {
        echo 'not exists';
    }
    ?>Warning: preg_match() [function.preg-match]: Compilation failed: regular expression is too large at offset 31311 in D:\www\htdocs\t.php on line 7
    not exists
      

  10.   

    那三个ini_set,好像是对$content变量有作用,对$bad_words不起作用。
      

  11.   

    一楼的代码在我这里运行正常,但是我应该不会用正则去做,把"000|22222|33333|4月25日|44444|66666|77777|81813|88888|99999|555555|恐怖"用explode分割成数组,然后用array_search查找是否存在匹配,当然这是精确匹配,如果是模糊匹配则需要用正则,但也不是像楼主这样做,作为PHP新手的意见啊,高手别见笑。
      

  12.   

    1 还是那句话,推荐用scws来处理。

    把 $bad_words 这个分个组吧。 一组里面只存20 个。
    $bad_words = "/000|22222|33333|4月25日|44444|66666|77777|81813|88888|99999|555555|恐怖/i";
      

  13.   

    楼主,我想是你服务器的事吧。检查一下系统再说。
    我当前正在用的badword.txt是16KB
    http://info.162100.com/inc/require/badword.txt