2012-03-02 33 views
5

tốt hơn Cho một tập tin đầu vào lớn trông như thế này:Làm thế nào để viết những dòng này trong perl

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 

tôi đang cố gắng để tìm hiểu số lượng các lỗi mỗi giờ; có nghĩa là, tôi đang tìm kiếm một tập tin đầu ra trông như thế này:

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

Dưới đây là một kịch bản mà đang làm việc cho tôi:

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

Nhưng với tính năng Perl, tôi khá chắc chắn này có thể được thực hiện trong ít dòng hơn. Tôi rất cảm kích nếu bạn có thể cung cấp một số ví dụ. Tôi hy vọng nó sẽ hữu ích cho những ai muốn giảm dòng mã được viết để đạt được điều gì đó.

+2

'sử dụng nghiêm ngặt; sử dụng cảnh báo; ' – Ether

+3

Không phải Perl, nhưng' sed 's /:.*//' | uniq -c' –

Trả lời

6

Những gì bạn có đã khá ngắn. Bạn có thể cải thiện mọi thứ một chút bằng cách sử dụng các tập tin từ vựng và kiểm tra giá trị trả về của mở.

Đây là một viết lại sử dụng một số tính năng cú pháp khác của 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 

Hoặc nếu bạn thực sự muốn nó ngắn, làm thế nào về một liner:

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

gọn gàng! - sẽ chấp nhận câu trả lời của bạn nếu không ai đăng bài nào tốt hơn. –

+3

Thay vì 'END', bạn có thể sử dụng toán tử hôn eskimo. '} {say ... keys% t''. – TLP

+2

Không chắc chắn nếu nó tốt hơn/ngắn hơn/dễ đọc hơn, nhưng đây là một cách dùng autosplit trên dấu hai chấm và toán tử eskimo: 'perl -F: -lanwe '$ a {$ F [0]} ++; } {print "$ _ -> $ a {$ _}" cho các khóa% a 'infile' – TLP

2

Bạn có thể tận dụng hiệu quả named capture groups, một tính năng mới kể từ phiên bản 5.10, để mô hình của bạn thể hiện ý định của bạn tốt hơn và tạo ra kết quả được sắp xếp chính xác.

Bạn có thể phân phối hoàn toàn với các số và tạo các nhóm chụp có tên. Ký hiệu là (?<name>...) để khai báo và \g{name} để tham chiếu. (Để tương thích với các biểu thức chính quy .NET, \g{name} cũng có thể được viết là \k{name}, \k<name> hoặc \k'name'.) tên không được bắt đầu bằng số, cũng không chứa dấu gạch nối. Khi các nhóm khác nhau trong cùng một mẫu có cùng tên, bất kỳ tham chiếu nào đến tên đó giả định nhóm được xác định ngoài cùng bên trái. Các nhóm được đặt tên được tính theo số lượng tuyệt đối và tương đối, và do đó cũng có thể được gọi bằng những con số đó. (Có thể thực hiện mọi việc với các nhóm chụp có tên theo cách khác, nếu không sẽ yêu cầu (??{}).)

Nội dung nhóm chụp được sắp xếp động và có sẵn cho bạn bên ngoài khối cho đến khi kết thúc thành công tiếp theo, tùy theo điều kiện nào đến Đầu tiên. (Xem báo cáo hợp chất trong perlsyn.) Bạn có thể tham chiếu đến chúng theo số tuyệt đối (sử dụng $1 thay vì \g1, v.v.); hoặc theo tên qua số %+ hash, sử dụng $+{name}.

Đối với mỗi dòng đầu vào, hãy tìm một kết quả phù hợp nhưng đặt các thành phần vào thứ tự YYYY/MM/DD để dễ dàng phân loại.

#! /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 

Output:

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

substr là hiệu quả hơn regex nếu có vấn đề. Nếu bạn có quyền truy cập vào CPAN, sắp xếp có thể được loại bỏ với Tie :: IxHash, trong đó giữ các phím theo thứ tự chèn (nhưng vẫn là một băm). (Tôi đã thêm một vài hàng khác minh họa vấn đề sắp xếp.)

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 

Nếu bạn không có quyền truy cập vào Tie :: IxHash thì đây là một phiên bản ngắn với một loại các phím (trừ lặp lại DỮ LIỆU).

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; 
Các vấn đề liên quan