2

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

 #!/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 模块可以否定重写它的需要?我没有运气找到类似的东西。提前致谢!

4

3 回答 3

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。

于 2013-02-10T01:13:46.207 回答
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))
于 2013-02-10T01:07:49.627 回答
1

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

我不在乎投反对票,因为人们应该知道如果可以在 shell 上完成,就没有理由在 20 行 python 中做事

< my_file.txt | sort | uniq > uniq_my_file.txt
于 2013-02-10T00:57:37.620 回答