我多年来一直在使用这个脚本来总结日志文件。
#!/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模块会否定需要重写它?我没有运气找到类似的东西。提前致谢!
答案 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