仅将日志文件汇总到唯一条目

时间:2013-02-10 00:53:38

标签: python perl

我多年来一直在使用这个脚本来总结日志文件。

 #!/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 个答案:

答案 0 :(得分:3)

正如var的名称所暗示的那样,

@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。

答案 1 :(得分: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))

答案 2 :(得分:1)

我不得不说我经常遇到的人试图在python perl中做一些东西可以在shell或bash上一行完成:

我不关心downvotes,因为人们应该知道没有理由在20行python中做东西,如果它可以在shell上完成

< my_file.txt | sort | uniq > uniq_my_file.txt