我有第一行的文件
=== Verbose logging started: 1/3/2017 17:41:55 Build type: SHIP UNICODE 5.00.7601.00 Calling process: C:\Windows\SysWOW64\msiexec.exe ===
Run Code Online (Sandbox Code Playgroud)
和最后一行
=== Verbose logging stopped: 1/3/2017 17:49:17 ===
Run Code Online (Sandbox Code Playgroud)
我对那些行(17:41:55和17:49:17)中的时间字段感兴趣,想要找到从开始到停止的时间差异.
我尝试在数组中读取文件并获取第一行和最后一行
my $last = pop (@array);
my $first = shift (@array);
Run Code Online (Sandbox Code Playgroud)
但是在阵列中进入时间领域变得越来越困难.
你能建议任何其他方式吗?
如果要读取可能非常大的日志文件的第一行和最后一行,则不应将其全部插入到数组中,因为它可能会占用大量内存.相反,只需阅读第一行和最后一行.
你可以很容易地阅读第一行.
use v5.10;
use strict;
use warnings;
use autodie;
open my $fh, $logfile;
my $first = <$fh>;
Run Code Online (Sandbox Code Playgroud)
您可以通过使用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;
Run Code Online (Sandbox Code Playgroud)
请注意,如果文件末尾有任何杂散换行符,那么这将是最后一行,因此您可能希望继续阅读,直到找到所需内容.
# Read lines backwards until we get something that
# contains non-whitespace.
while( my $last = $backwards->readline ) {
last if $last =~ /\S+/;
}
Run Code Online (Sandbox Code Playgroud)
这是一个更简单但更慢(对于大文件)获取第一行和最后一行的方法.像以前一样读取第一行,然后读取每一行,但只保留最后一行.
my $last;
while( my $line = <$fh> ) { $last = $line }
Run Code Online (Sandbox Code Playgroud)
它仍然必须读取整个文件,但它只保留最后一个在内存中.
完成后,您可以解析该行并将其转换为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");
}
Run Code Online (Sandbox Code Playgroud)
strptime是许多语言用来解析日期的函数(字符串解析时间).strftime(字符串格式时间)用于格式化日期.他们共享相同的迷你语言.看看strftime文档,了解那里发生了什么.
一旦你有了,你可以通过减去它们来获得差异.
my $start = log_time($first);
my $end = log_time($last);
say "Seconds elapsed: ".$end - $start;
Run Code Online (Sandbox Code Playgroud)