2017-01-09 83 views
1

我與一線文件在Perl讀第一和最後一個行解析

=== Verbose logging started: 1/3/2017 17:41:55 Build type: SHIP UNICODE 5.00.7601.00 Calling process: C:\Windows\SysWOW64\msiexec.exe === 

和最後一行文件

=== Verbose logging stopped: 1/3/2017 17:49:17 === 

我在那些線(17:41:5517:49:17)感興趣的時間字段,希望找到從開始到停止的時間差異。

我試圖讀取數組中的文件並獲取第一和最後一個行

my $last = pop (@array); 
my $first = shift (@array); 

但要以時間域陣列變得困難。

您能否建議任何替代方法?

+0

[讀取最後一行(http://stackoverflow.com/questions/36568162/how- do-i-read-the-last-line-of-a-file-with-a-bare-perl-on-windows /36570096) – mkHun

回答

6

如果你想讀取一個潛在的非常大的日誌文件的第一行和最後一行,你不應該把它全部寫入一個數組,因爲它可能會消耗大量的內存。相反,只要閱讀第一行和最後一行。

您可以輕鬆閱讀第一行。

use v5.10; 
use strict; 
use warnings; 
use autodie; 

open my $fh, $logfile; 
my $first = <$fh>; 

您可以閱讀使用seek跳轉到文件的末尾,然後與read塊讀取向後,直到你得到一整行的最後一行。這可能會變得複雜。幸運的是File::ReadBackwards可以爲你做到這一點。

use Carp; 
use File::ReadBackwards; 

my $backwards = File::ReadBackwards->new($logfile) 
    or croak "Can't open $logfile: $!"; 
my $last = $backwards->readline; 

注意,如果在文件末尾的任何雜散換行符這些將是最後一行,所以你可能想繼續讀書,直到你得到你所要尋找的。

# Read lines backwards until we get something that 
# contains non-whitespace. 
while(my $last = $backwards->readline) { 
    last if $last =~ /\S+/; 
} 

這裏有一個簡單,但速度較慢(大文件)的方式來獲得第一和最後一行。像以前一樣閱讀第一行,然後閱讀每一行,但只保留最後一行。

my $last; 
while(my $line = <$fh>) { $last = $line } 

它仍然要讀取整個文件,但它只保留最後一個在內存中。


一旦你有,你可以解析線,把它變成一個Time::Piece物體更容易的工作。

# === Verbose logging started: 1/3/2017 17:41:55 ... === 
# === Verbose logging stopped: 1/3/2017 17:49:17 === 
sub log_time { 
    my $line = shift; 

    # This captures the 1/3/2017 17:49:17 part 
    my($datetime) = $line =~ 
     /^=== Verbose logging (?:started|stopped):\s*(\d+/\d+/\d+\s+\d+:\d+:\d+)/; 

    # Parse it into a Time::Piece object. 
    return Time::Piece->strptime($datetime, "%m/%d/%Y %H:%M:%S"); 
} 

strptime是許多語言用來解析日期(字符串解析時間)的函數。 strftime(字符串格式時間)用於格式化日期。他們分享相同的迷你語言。看看strftime文檔瞭解那裏發生了什麼。

一旦你有,you can get the difference in seconds by subtracting them

my $start = log_time($first); 
my $end = log_time($last); 

say "Seconds elapsed: ".$end - $start; 
2

我有一個稍微較不復雜的方法來Schwern擁有這是使用Unix命令:

#!/usr/bin/perl 

use strict; 
use English; 

my $first=`head -1 $ARGV[0]`; 
my $last=`tail -1 $ARGV[0]`; 

print "$first\n"; 
print "$last\n"; 
+0

我相信'tail -1'會從文件尾部讀取,所以它避免了讀取整個文件。不要使用原型;他們不是功能簽名,他們是爲了非常專業的目的。如果您想要函數簽名,請在較新的Perls中使用[Method :: Signatures](http://metacpan.org/pod/Method:Signatures)或'use feature'簽名''。最後,不需要寫'command()',[反引號](http://perldoc.perl.org/perlop.html#Quote-Like-Operators)會爲你做。 '''我的$ first ='頭-1 $ ARGV [0]'''' – Schwern

+1

@Schwern謝謝,我想我已經靜靜地呆了15年了。我已經更新了我的答案,謝謝。 –

+0

你爲什麼要'使用英語'?你實際上沒有使用任何變量名稱。 – simbabque

相關問題