我为我们公司的网页编写了一些PHP脚本,它记录了每个访问者的IP地址,日期和时间戳,并在客户端浏览器中注入了一个cookie来跟踪终身访问次数。它以这种格式将所有这些信息打印到访问日志中。
Visitor IP: 173.11.250.189
Date = Wednesday 12-23-2015
Time = 09:47:16am
# of Visits:1
Visitor IP: 173.11.250.189
Date = Wednesday 12-23-2015
Time = 09:47:40am
# of Visits:2
Visitor IP: 173.11.250.189
Date = Wednesday 12-23-2015
Time = 09:47:46am
# of Visits:3
Visitor IP: 173.11.250.192
Date = Wednesday 12-23-2015
Time = 09:57:40am
# of Visits:1
Visitor IP: 173.11.250.192
Date = Wednesday 12-23-2015
Time = 09:57:54am
# of Visits:2
Visitor IP: 173.11.250.189
Date = Wednesday 12-23-2015
Time = 10:20:04am
# of Visits:4
Visitor IP: 173.11.250.176
Date = Wednesday 12-23-2015
Time = 10:20:32am
# of Visits:1
如果cookie present = false,则只注入一个值为1的新cookie,并在Access Log中输出默认值1。
我每周都有一个cron作业,它运行一个脚本,通过电子邮件将此日志通过电子邮件发送给我自己以及公司所有者,然后创建此日志的存档,最后清除日志并重新开始。
除了一个事实......冗余条目之外,它的效果很好。 我正在尝试找到一种方法来删除此日志中的冗余,然后再通过电子邮件发送给所有者和我自己。例如,上面列出的两个条目都共享相同的IP地址,但它们标记了两个单独的访问。对于冗余条目,我希望仅保留具有最高访问次数的条目,同时删除包含较低访问次数的冗余条目。
上面给出的样本的过滤输出类似于:
Visitor IP: 173.11.250.189
Date = Wednesday 12-23-2015
Time = 10:20:04am
# of Visits:4
Visitor IP: 173.11.250.192
Date = Wednesday 12-23-2015
Time = 09:57:54am
# of Visits:2
Visitor IP: 173.11.250.176
Date = Wednesday 12-23-2015
Time = 10:20:32am
# of Visits:1
如果仅存储最近访问的详细信息,并且发现来自同一IP的多次访问,则仅保留最近访问次数较高的记录。
有什么想法吗?
我还没有真正能够提出任何解决方案,因为它要求过滤一次考虑4行而不仅仅是线到线过滤,因为每4行是一个“条目” ”。我对这个很难过。
最诚挚的问候, 马修奥。
答案 0 :(得分:1)
这可能会有所帮助:
#!/bin/bash
# Records are separated by blank lines.
# Each line is one field.
sed -n '{1!G;h;$p}' $1 | awk 'BEGIN {RS="";FS="\n";OFS="\n";ORS="\n\n"}
{
if(!seen[$4]++)
{
print $4,$3,$2,$1
}
}'
将脚本保存为RedundantRecordRemover
,使其成为可执行文件,
然后运行它:
./RedundantRecordRemover your_log_file
实际上您可以通过以下方式替换原始文件:
./RedundantRecordRemover your_log_file >> tempfile ; mv tempfile your_log_file
理念:
sed
脚本在将文本传递给awk
脚本之前将文本从您提供给它的文件中反转。此文本撤消在定位每个IP地址的最后一个条目时非常有用。
要求:
输入日志文件中的每条记录必须用空行分隔。这是您的示例输入文件所说的内容。
<强>亡 - 强>
大型日志文件可能有speed bottleneck
。不幸的是,我无法在我的环境中测试大型日志文件。我想这应该适用于几兆字节大小的文件。
注意:我认为 -
修改强>
结合@ fedorqui的建议,另一种编写脚本的方式是:
#!/bin/bash
# Records are separated by blank lines.
# Each line is one field.
awk 'BEGIN {RS="";FS="\n";OFS="\n";ORS="\n\n"}
{
if(!seen[$4]++)
{
print $4,$3,$2,$1
}
}' <(tac $1)