取一个数组的前1000条数值

QQ785468931 2012-03-29 10:58:20
<?php

$fn = '/var/log/haproxy.log.2';
$fp = fopen($fn, 'r') or die("file open $fn false");
while($s = fgets($fp)) {
preg_match('/\[[\d.:]+\].+\[([\d.:]+)\]/', $s, $r);
if(empty($r[1])) continue;
@$res[$r[1]]++;
}



fclose($fp);
asort($res);

print_r($res);
?>
...全文
596 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
foolbirdflyfirst 2012-03-29
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

我们公司要求用PHP啊,再说awk我也不了解
[/Quote]
你的文件有多大?
awk + 管道 + sort和head 一行命令应该可以满足你的需求,效率相应也高些.
QQ785468931 2012-03-29
  • 打赏
  • 举报
回复
我们公司要求用PHP啊,再说awk我也不了解
foolbirdflyfirst 2012-03-29
  • 打赏
  • 举报
回复
看样子真是linux,不能用awk么,一定要php?
QQ785468931 2012-03-29
  • 打赏
  • 举报
回复
amani11说的很对,但放到255个文件,不如先分割数组吧
QQ785468931 2012-03-29
  • 打赏
  • 举报
回复
是啊,这样完成了,但是很慢啊
<?php

$fn = '/var/log/haproxy.log.2';
$fp = fopen($fn, 'r') or die("file open $fn false");
while($s = fgets($fp)) {
preg_match('/\[[\d.:]+\].+\[([\d.:]+)\]/', $s, $r);
if(empty($r[1])) continue;
@$res[$r[1]]++;
}



fclose($fp);
rsort($res);

print_r(array_slice($res,0,1000));
?>
cyzz 2012-03-29
  • 打赏
  • 举报
回复
换个思路解决问题
xuzuning 2012-03-29
  • 打赏
  • 举报
回复
呵呵,搞错了!#3是只取前1000条记录

应该是
$res = array_slice($res, 0, 1000);
xuzuning 2012-03-29
  • 打赏
  • 举报
回复
$i= 0;
$fp = fopen($fn, 'r') or die("file open $fn false");
while($s = fgets($fp) && $i++<1000) {
preg_match('/\[[\d.:]+\].+\[([\d.:]+)\]/', $s, $r);
if(empty($r[1])) continue;
@$res[$r[1]]++;
}
amani11 2012-03-29
  • 打赏
  • 举报
回复
你的需求这样是解决不了的

要分开处理。。。。。

比如,可将ip按第一位,写到255个文件里面,,,也可以将ip转换成数字,这样处理后续可以少用点内存

分别在255个文件里面,找出前1000名。。。因为每组至多包含2^24个不同的数【暂时不考虑ipv6】,这个内存可接受的
这样用一个数组遍历,复杂度O(n),即可找出前1000

最后维护一个1000的有序数组,往里面插入数据即可,超过1000,弹出最小的那个
代码如诗 2012-03-29
  • 打赏
  • 举报
回复
array_slice($res,0,1000);
QQ785468931 2012-03-29
  • 打赏
  • 举报
回复
Mar 8 12:51:27 10.10.255.5 haproxy[4840]: 124.240.66.100:42408[10.10.255.5:36236]->112.90.32.240:80[112.90.32.240:80] [08/Mar/2012:12:51:26.939] http_check http_image/<NOSRV> 12/0/24/30/91 200 18990 - - ---- 541/541/9/0/0 0/0 {img.alim
ama.cn|http://www.taobao.com/go/act/sale/250x250men.php?pid=mm_17936709_2306571_8939881&refpos=,a,null&pid=mm_17936709_2306571_8939881&pvid=2_1331182226_146363p2_163744779} "GET /cms/images/1323674511466.jpg HTTP/1.1"
用正则这样取域名报错
preg_match('([A-Za-z0-9]+\.)+[A-Za-z0-9]+/', $s, $r);
Warning: arsort() expects parameter 1 to be array, null given in D:\软件\php-5.2
.1-Win32\newfile10.php on line 12

Warning: array_slice(): The first argument should be an array in D:\软件\php-5.2
.1-Win32\newfile10.php on line 13
QQ785468931 2012-03-29
  • 打赏
  • 举报
回复
域名和URL我还都没有取出来,#6那个代码在服务器上可以运行,但是速度比较慢
带我那个人的意思是,以后我要处理的文件会更大,这样写不行
要学会分段处理
他说的好像是要我写一个函数每次取出1万的数据量,用完再清空
然后另外写一个函数把处理结果和这次读取的数据合起来
foolbirdflyfirst 2012-03-29
  • 打赏
  • 举报
回复
早说练手嘛,早说我就不在这瞎掺和了。
在你#6代码的基础上,开多两个数组,分别统计域名和URL的,不要多次读文件哈。
QQ785468931 2012-03-29
  • 打赏
  • 举报
回复
因为我是新人,目前是练手
需求如下
(1)、目标IP统计,统计出访问最多的前1000个目标IP,相关报表结构如下:
IP地址 总访问次数 访问主域名1/访问次数 访问主域名2/访问次数 访问主域名3/访问次数 ......
10.10.255.31 1000 Efly.cc/230 Abc.cn/240 Cdf.com/280 .......
(2)、域名统计,统计出访问最多的前1000个域名,相关报表信息如下:
域名 总访问次数 响应IP1/访问次数 响应IP2/访问次数 ......
efly.cc 1000 202.96.128.86/100 202.96.128.166/200 .......
(3)、URL统计,统计出访问最多的前1000个URL,相关报表信息如下:
URL 总访问次数 响应IP1/访问次数 响应IP2/访问次数 .....
Efly.cc/index.php 1000 202.96.128.86/100 202.96.128.166/200 ......
是要处理后的1000个结果。
xuzuning 2012-03-29
  • 打赏
  • 举报
回复
是处理前1000的记录,还是取处理后的前1000个结果?
这是完全不同的两件事

你应该考虑到:
1、你是在处理日志文件,而日志文件的数据是追加方式的:老的在前面,新的在后面
2、如果你只取处理后的前1000个结果,如何保证你最关注的内容在其中
3、分析日志时,只要目的和算法确定了。从此时此刻开始,之前的记录只需处理一次,将结果缓存下来就可以了。因为他们已经不会再改变了
4、分次处理时需要记录下本次分析的最后位置,下次处理时就从这里开始
foolbirdflyfirst 2012-03-29
  • 打赏
  • 举报
回复
就是说你们有多个日志文件,每日递增,你现在要对所有日志文件做个统计,对吧?
你们单个日志文件最大能有多大?
我上次网上看到篇博文,博主说用awk处理一个1G多的文件做统计,花费的时间是1分半左右。
不知道你用php #6的代码处理花费了多长时间,文件多大?
QQ785468931 2012-03-29
  • 打赏
  • 举报
回复
他说以后处理几十T的文件都有可能
读取一定的文件块后 得到的数组肯定是比较大的 和上一次的结果合并之后就更到了 由于我们只需要前1000的记录 所以 每一次合并完结果后 在需要在内存中保存好 前10000条记录就可以了

21,886

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧