如何在perl中更好地编写这个

rin*_*rer 5 optimization perl hash coding-style

给定一个大的输入文件,如下所示:

02/26/2012 08:54:38 Error:java.sql.Exception
02/26/2012 08:54:48 Error:java.sql.Exception
02/26/2012 08:56:05 Error:java.sql.Exception
02/26/2012 08:57:21 Error:java.sql.Exception
02/26/2012 08:59:29 Error:java.sql.Exception
02/26/2012 09:01:14 Error:java.sql.Exception
02/26/2012 09:08:48 Error:java.sql.Exception
02/26/2012 09:10:41 Error:java.sql.Exception
Run Code Online (Sandbox Code Playgroud)

我试图找出每小时的错误数; 也就是说,我正在寻找一个如下所示的输出文件:

02/26/2012 08 -> 5
02/26/2012 09 -> 3
Run Code Online (Sandbox Code Playgroud)

这是一个适合我的脚本:

#!/bin/perl
open(MYFILE, 'tata2');
my %table;
while (<MYFILE>) {
     chomp;
     $dtkey = substr $_, 0, 13;
     $table{$dtkey}++;
}
close(MYFILE); 
for my $key (keys %table) {
    print "$key -> $table{$key}\n";
}
Run Code Online (Sandbox Code Playgroud)

但鉴于Perl的功能,我很确定这可以用更少的行完成.如果你能提供一些例子,我将不胜感激.我希望它对那些想要减少为实现某些目的而编写的代码行的人有用.

Eri*_*rom 6

你拥有的已经很短了.您可以通过使用词法文件句柄并检查open的返回值来改进一些事情.

这是使用Perl的一些其他语法功能的重写:

open my $fh, '<', 'filename' or die $!;
my %table;

while (<$fh>) {
    $table{$1}++ if /([^:]+)/ # regex is a bit shorter than the substr
}

print "$_ -> $table{$_}\n" for keys %table;  # statement modifier form
Run Code Online (Sandbox Code Playgroud)

或者,如果你真的想要它简短,那么一个班轮怎么样:

perl -lnE '$t{$1}++ if /([^:]+)/; END {say "$_ -> $t{$_}" for keys %t}' infile
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用eskimo kiss运算符代替`END`.`} {say ... keys%t'`. (3认同)
  • 不确定它是否更好/更短/更具可读性,但这里有一个在冒号和eskimo运算符上使用autosplit:`perl -F:-lanwe'$ a {$ F [0]} ++; 键盘%a'infile`的{print"$ _ - > $ a {$ _}" (2认同)