仅汇总唯一条目的日志文件
我在工作中已经用这个脚本好几年了,主要是用来总结日志文件。
#!/usr/bin/perl
$logf = '/var/log/messages.log';
@logf=( `cat $logf` );
foreach $line ( @logf ) {
$line=~s/\d+/#/g;
$count{$line}++;
}
@alpha=sort @logf;
$prev = 'null';
@uniq = grep($_ ne $prev && ($prev = $_), @alpha);
foreach $line (@uniq) {
print "$count{$line}: ";
print "$line";
}
我一直想用Python重写它,但有些部分我不是很理解,比如:
@alpha=sort @logf;
$prev = 'null';
@uniq = grep($_ ne $prev && ($prev = $_), @alpha);
有没有人知道有没有Python的模块可以让我不用重写这个?我找了很久都没找到类似的东西。谢谢大家!
3 个回答
1
我得说,我经常看到有人在用Python做一些事情,而这些事情在Shell或Bash里只需要一行代码就能完成。
我不在乎被点踩,因为大家应该明白,如果在Shell里能用一行代码搞定的事情,就没必要用20行Python去做。
< my_file.txt | sort | uniq > uniq_my_file.txt
3
正如变量的名字所暗示的,
@alpha=sort @logf;
$prev = 'null';
@uniq = grep($_ ne $prev && ($prev = $_), @alpha);
这个过程是在找出独特的元素(也就是去掉重复的行),同时忽略行中的数字,因为这些数字之前已经被替换成了#
。这三行可以写成
@uniq = sort keys(%count);
或者甚至可以写成
@uniq = keys(%count);
在Perl中还有另一种写这个程序的方法:
my $log_qfn = '/var/log/messages.log';
open(my $fh, '<', $log_qfn)
or die("Can't open $log_qfn: $!\n");
my %counts;
while (<$fh>) {
s/\d+/#/g;
++$counts{$_};
}
#for (sort keys(%counts)) {
for (keys(%counts)) {
print "$counts{$_}: $_";
}
这样写应该更容易转换成Python。
2
@alpha=sort @logf;
$prev = 'null';
@uniq = grep($_ ne $prev && ($prev = $_), @alpha);
这相当于
uniq = sorted(set(logf))
如果logf
是一系列行的话。
不过,由于你是在统计行的出现频率,你可以使用collections.Counter来同时统计行数和收集唯一的行(作为键),这样就不需要再计算uniq
了:
count = collections.Counter()
for line in f:
count[line] += 1
import sys
import re
import collections
logf = '/var/log/messages.log'
count = collections.Counter()
write = sys.stdout.write
with open(logf, 'r') as f:
for line in f:
line = re.sub(r'\d+','#',line)
count[line] += 1
for line in sorted(count):
write("{c}: {l}".format(c = count[line], l = line))