综合匿名函数 php7的call()以及yield 生成器 进行日志ip解析

1. 大致思路, 现有日志文件, 需要分析日志中 对应ip出现的频率, 按照从大到小排列

  首先建立一个类

use Exception;
use SplFileObject;
class Access
{
    const ERROR_UNABLE = 'ERROR: unable to open file';
    protected  $log;
    public $frequency=array();
    public function __construct($filename){
        if (!file_exists($filename)){
            $message=__METHOD__.':'.self::ERROR_UNABLE.PHP_EOL;
            $message.=strip_tags($filename).PHP_EOL;
            throw  new Exception($message);
        }
        $this->log=new SplFileObject($filename,'r');

    }
    // 生成器  // 实际$count没有作用
    public function fileIteratorByLine(){
        $count=0;
        while (!$this->log->eof()){
            yield $this->log->fgets();
            $count++;
        }
        return $count;
    }
    // 执行查找操作
    public function getIp($line){
        preg_match_all('/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/',$line,$match);
        return $match[1]??'';
    }



}

 

调用执行 

define('LOG_FILES','./serverlog.logbak');
include '../Autoload/Loader.php';
\Application\Autoload\Loader::init(__DIR__.'/../..');  // 引入自动加载
$freq=function ($line) {    // 闭包
    $ip =$this->getIp($line);
  if ($ip){
      if (is_array($ip)){
          foreach ($ip as $value){
              echo '.';
              $this->frequency[$value]=(isset($this->frequency[$value]))?$this->frequency[$value]+1:1;
          }
      }


  }
};
foreach (glob(LOG_FILES) as $server){
    echo '<br>'.$server.'<br>';
    $access=new \Application\Web\Access($server);
    foreach ($access->fileIteratorByLine() as $line){
        $freq->call($access,$line);  // 闭包使用
    }
}
asort($access->frequency);
foreach ($access->frequency as $key=>$value){
    printf('%16s:%6d'.'<br>',$key,$value);
}

 输出结果 

 

  总结:

   使用了

       1.php7 新特性 call()

       2.yield 语法生成器 加快运行

       3.preg_match/preg_match_all 匹配

       4.引入  SplFileObject   以对象的方式打开文件

posted @ 2021-07-14 15:26  飘柔2019  阅读(95)  评论(0编辑  收藏  举报