2012-03-02 17 views
5

bu daha iyi yazmak için: Ben saatte hataların sayısını öğrenmek için çalışıyorumşöyle büyük bir giriş dosyası Verilen perl'de

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 

; yani ben şöyle bir çıktı dosyası için arıyorum: Bu can eminim,

#!/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"; 
} 

Ama verilen Perl'in özellikleri: Burada

02/26/2012 08 -> 5 
02/26/2012 09 -> 3 

bir benim için çalışıyor script Daha az satırda yapılmalıdır. Bazı örnekler verebiliyorsanız çok memnun olurum. Bir şeyi başarmak için yazılan kod satırlarını azaltmak isteyenler için yararlı olacaktır.

+2

'use strict; uyarıları kullan; ' – Ether

+3

Perl değil, ama 'sed'/..*// '| uniq -c' –

cevap

6

Halihazırda oldukça kısa. Sözcüksel dosya tutamaçlarını kullanarak ve açıklığın dönüş değerini kontrol ederek bazı şeyleri geliştirebilirsiniz.

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

neat! - kimse daha iyi bir şey göndermezse cevabınızı kabul eder. –

+3

"END" yerine eskimo öpücüğü operatörünü kullanabilirsiniz. '} {say ... tuşları% t''. – TLP

+2

Daha iyi/daha kısa/okunabilir olup olmadığından emin değilsiniz, ancak kolonda ve eskimo operatöründe autosplit kullanan bir tanesi: 'perl -F: -lanwe '$ a {$ F [0]} ++; } {print "$ _ -> $ a {$ _}"% a 'infile' tuşları için – TLP

2

Sen etkin kullanımı yapabilirsiniz: Eğer gerçekten bir tek astar hakkında nasıl, kısa istiyorsanız

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 

Veya: Burada

Perl'in diğer sözdizimsel bazı özelliklerini kullanarak bir yeniden olduğunu Deseninizin amacınızı daha iyi ifade etmesi ve doğru şekilde sıralanmış çıktı üretmesini sağlamak için, sürüm 5.10'dan bu yana yeni bir özellik olan named capture groups.

Rakamlarla tamamen dağıtıp, adlandırılmış yakalama grupları oluşturabilirsiniz. Bildirim, bildirmek için (?<name>...) ve başvuru için \g{name} şeklindedir. (.NET normal ifadeleriyle uyumlu olması için, da \k{name}, \k<name> veya \k'name' olarak yazılabilir.) adı bir numarayla başlamalıdır ve tire içermemelidir. Aynı modeldeki farklı gruplar aynı ada sahip olduğunda, bu adla ilgili herhangi bir referans en soldaki tanımlanmış grubu kabul eder. Adlandırılmış gruplar mutlak ve göreli numaralandırma olarak sayılır ve bu sayılar tarafından da belirtilebilir. (Aksi takdirde (??{}) gerektirecek isimlendirilmiş yakalama grupları ile şeyler yapmak mümkündür.)

Yakalama grubu içeriği dinamik olarak kapsamlandırılır ve kapsayıcı bloğun sonuna kadar ya da sonraki başarılı eşleşmeye kadar desen dışında sizin için kullanılabilir (hangisi gelirse) ilk. (Perlsyn'deki Bileşik İfadeleri'ne bakın.) Onlara mutlak sayı ile başvurabilirsiniz (\g1, vb yerine $1 kullanarak); veya $+{name} kullanarak %+ hash aracılığıyla adlandırın. Her bir satır için bir eşleşme olup, parçaların kolay bir şekilde ayrılması için YYYY/AA/DD HH sırasına izin verin.

#! /usr/bin/env perl 

use strict; 
use warnings; 

use 5.10.0; # named capture buffers 

*ARGV = *DATA; # for demo only; remove for real use 

my %hour_errors; 
while (<>) { 
    $hour_errors{"$+{y}/$+{m}/$+{d} $+{h}"}++ 
    if m!^ (?<m> \d+)/(?<d> \d+)/(?<y> \d+) \s+ (?<h> \d+) :!x; 
} 

print "$_ -> $hour_errors{$_}\n" for sort keys %hour_errors; 

__DATA__ 
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 

Çıktı:

2012/02/26 08 -> 5 
2012/02/26 09 -> 3
1

substr bu konularda regex daha etkilidir. CPAN'a erişiminiz varsa, bu tür anahtarlar, düzen içinde (ancak yine de bir karma) anahtarı dahili olarak tutan Tie :: IxHash ile ortadan kaldırılabilir. (Sıralama sorununu gösteren birkaç satır daha ekledim.)

use Tie::IxHash; 
tie my %table, 'Tie::IxHash'; 
$table{substr $_, 0, 13}++ while <DATA>; 
print "$_ -> $table{$_}\n" for keys %table; 
__DATA__ 
02/26/2012 09:10:41 Error:java.sql.Exception 
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 
03/26/2012 08:54:38 Error:java.sql.Exception 
03/26/2012 08:54:48 Error:java.sql.Exception 
03/26/2012 08:56:05 Error:java.sql.Exception 
03/26/2012 08:57:21 Error:java.sql.Exception 
03/26/2012 08:59:29 Error:java.sql.Exception 
03/26/2012 09:01:14 Error:java.sql.Exception 
03/26/2012 09:08:48 Error:java.sql.Exception 
04/26/2012 08:54:38 Error:java.sql.Exception 
04/26/2012 08:54:48 Error:java.sql.Exception 
04/26/2012 08:56:05 Error:java.sql.Exception 
04/26/2012 08:57:21 Error:java.sql.Exception 
04/26/2012 08:59:29 Error:java.sql.Exception 
04/26/2012 09:01:14 Error:java.sql.Exception 
04/26/2012 09:08:48 Error:java.sql.Exception 
04/26/2012 09:10:41 Error:java.sql.Exception 

sonra burada Tie :: iXhash erişimi olan anahtarlar (eksiDATA tekrarlayarak) bir çeşit kısa versiyonu yoksa.

my %table; 
$table{substr $_, 0, 13}++ while <DATA>; 
print "$_ -> $table{$_}\n" for sort { "@{[($a=~/(\d+)\D?/g)[2,1,0,3]]}" cmp "@{[($b=~/(\d+)\D?/g)[2,1,0,3]]}" } keys %table;