Perl:提取时间戳的开始和结束日期
Perl: Extracting begin and End date for timestamps
需要帮助提取以下日期和时间戳列表中的开始和结束日期
假设我从日志文件中提取了以下时间戳数据,并且只需要提取每个日期和时间的开始和结束。
输出将用于计算开始到结束之间的时间差。
数据
2021 年 11 月 16:27:39
2021 年 11 月 16:28:10
2021 年 11 月 16:30:47
2021 年 11 月 16:30:47
2021 年 12 月 09:27:03
2021 年 12 月 10:27:03
2021 年 12 月 18:22:15
2021 年 13 月 08:57:16
2021 年 13 月 08:57:37
2021 年 13 月 11:33:25
2021 年 13 月 11:33:25
2021 年 11 月 8 日 16:45:17
2021 年 11 月 8 日 16:49:10
2021 年 11 月 8 日 17:00:50
2021 年 11 月 8 日 22:10:24
2021 年 11 月 9 日 11:51:35
2021 年 11 月 9 日 11:52:40
2021 年 11 月 9 日 12:14:39
2021 年 11 月 9 日 14:23:10
...
...
...
预期输出
开始:2021 年 11 月 16:27:39
结束时间:2021 年 11 月 16:30:47
开始:2021 年 12 月 09:27:03
结束时间:2021 年 12 月 18:22:15
开始时间:2021 年 13 月 08:57:16
结束时间:2021 年 10 月 13 日 11:33:25
开始时间:2021 年 11 月 8 日 16:45:17
结束时间:2021 年 11 月 8 日 22:10:24
开始时间:2021 年 11 月 9 日 11:51:35
结束时间:2021 年 11 月 09 日 14:23:10
下面是我的脚本,但我只设法提取了开始数据
%key;
while ( <IN> ) {
$_=~ s/^\s+|\s+$//g;
my ($saved_date, $record_date);
chomp ;
my ($k, $d) = split;
if (! exists $key{ $k } ) {
$key{ $k } = $d;
my ($dtformat) = $d =$dtformat;
$end_date = Time::Piece->strptime($_, $dtformat);
next;
my ($dtformat) = $key{ $k } = $dtformat;
$saved_date = Time::Piece->strptime($_, $dtformat);
my ($dtformat) = $d =$dtformat;
$record_date = Time::Piece->strptime($_, $dtformat);
if ( $record_date - $saved_date > 0 ) {
$key{ $k } = $d;
}
}
}#endofwhile
for ( sort keys %key ) {
print "begin: ", $_, " ",$key{ $_ },"\n";
}
输出
开始:2021 年 11 月 8 日 16:45:17
开始:2021 年 11 月 9 日 11:51:35
开始:2021 年 10 月 21:59:39
开始:2021 年 10 月 11 日 00:21:46
开始:2021 年 12 月 09:27:03
开始:2021 年 10 月 13 日 08:57:16
开始:2021 年 9 月 30 日 00:21:23
需要帮助如何获得“结束”部分
谢谢
秘诀在于您用来存储数据的数据结构。由于您对一天的第一个和最后一个时间戳感兴趣,因此我构建了一个以日期为键值的散列,其中值是一个包含当天所有时间戳的数组。然后我们可以对每一天的时间戳进行排序,并轻松提取最早和最晚的。
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
use Time::Piece;
# The hash where we'll store our data
my %dates;
# The format of our dates
my $date_format = '%Y-%b-%d %H:%M:%S';
# Read each data item from DATA (or wherever)
while (<DATA>) {
# Remove the newline
chomp;
# Parse the string into a Time::Piece object
my $date = Time::Piece->strptime($_, $date_format);
# Store the object in our hash of arrays
push @{$dates{$date->ymd}}, $date;
}
# Get the list of hash keys sorted by date.
for (sort keys %dates) {
# For each date key...
# Get the sorted list of dates into an array...
my @times = sort { $a->hms cmp $b->hms } @{ $dates{$_} };
# And print the first and last elements of the array,
# using the correct format string.
say "begin: ", $times[0]->strftime($date_format);
say "end: ", $times[-1]->strftime($date_format);
}
__DATA__
2021-Oct-11 16:27:39
2021-Oct-11 16:28:10
2021-Oct-11 16:30:47
2021-Oct-11 16:30:47
2021-Oct-12 09:27:03
2021-Oct-12 10:27:03
2021-Oct-12 18:22:15
2021-Oct-13 08:57:16
2021-Oct-13 08:57:37
2021-Oct-13 11:33:25
2021-Oct-13 11:33:25
2021-Nov-08 16:45:17
2021-Nov-08 16:49:10
2021-Nov-08 17:00:50
2021-Nov-08 22:10:24
2021-Nov-09 11:51:35
2021-Nov-09 11:52:40
2021-Nov-09 12:14:39
2021-Nov-09 14:23:10
由于输入是排序的,所以你需要的是:
my ( $prev_line, $prev_d );
while ( my $line = <> ) {
my ( $d ) = split( ' ', $line );
if ( !$prev_line ) {
print "begin: $line";
$prev_d = $d;
}
elsif ( $d ne $prev_d ) {
print "end: $prev_line";
print "begin: $line";
$prev_d = $d;
}
$prev_line = $line;
}
if ( $prev_line ) {
print "end: $prev_line";
}
需要帮助提取以下日期和时间戳列表中的开始和结束日期
假设我从日志文件中提取了以下时间戳数据,并且只需要提取每个日期和时间的开始和结束。
输出将用于计算开始到结束之间的时间差。
数据
2021 年 11 月 16:27:39
2021 年 11 月 16:28:10
2021 年 11 月 16:30:47
2021 年 11 月 16:30:47
2021 年 12 月 09:27:03
2021 年 12 月 10:27:03
2021 年 12 月 18:22:15
2021 年 13 月 08:57:16
2021 年 13 月 08:57:37
2021 年 13 月 11:33:25
2021 年 13 月 11:33:25
2021 年 11 月 8 日 16:45:17
2021 年 11 月 8 日 16:49:10
2021 年 11 月 8 日 17:00:50
2021 年 11 月 8 日 22:10:24
2021 年 11 月 9 日 11:51:35
2021 年 11 月 9 日 11:52:40
2021 年 11 月 9 日 12:14:39
2021 年 11 月 9 日 14:23:10
...
...
...
预期输出
开始:2021 年 11 月 16:27:39
结束时间:2021 年 11 月 16:30:47
开始:2021 年 12 月 09:27:03
结束时间:2021 年 12 月 18:22:15
开始时间:2021 年 13 月 08:57:16
结束时间:2021 年 10 月 13 日 11:33:25
开始时间:2021 年 11 月 8 日 16:45:17
结束时间:2021 年 11 月 8 日 22:10:24
开始时间:2021 年 11 月 9 日 11:51:35
结束时间:2021 年 11 月 09 日 14:23:10
下面是我的脚本,但我只设法提取了开始数据
%key;
while ( <IN> ) {
$_=~ s/^\s+|\s+$//g;
my ($saved_date, $record_date);
chomp ;
my ($k, $d) = split;
if (! exists $key{ $k } ) {
$key{ $k } = $d;
my ($dtformat) = $d =$dtformat;
$end_date = Time::Piece->strptime($_, $dtformat);
next;
my ($dtformat) = $key{ $k } = $dtformat;
$saved_date = Time::Piece->strptime($_, $dtformat);
my ($dtformat) = $d =$dtformat;
$record_date = Time::Piece->strptime($_, $dtformat);
if ( $record_date - $saved_date > 0 ) {
$key{ $k } = $d;
}
}
}#endofwhile
for ( sort keys %key ) {
print "begin: ", $_, " ",$key{ $_ },"\n";
}
输出
开始:2021 年 11 月 8 日 16:45:17
开始:2021 年 11 月 9 日 11:51:35
开始:2021 年 10 月 21:59:39
开始:2021 年 10 月 11 日 00:21:46
开始:2021 年 12 月 09:27:03
开始:2021 年 10 月 13 日 08:57:16
开始:2021 年 9 月 30 日 00:21:23
需要帮助如何获得“结束”部分
谢谢
秘诀在于您用来存储数据的数据结构。由于您对一天的第一个和最后一个时间戳感兴趣,因此我构建了一个以日期为键值的散列,其中值是一个包含当天所有时间戳的数组。然后我们可以对每一天的时间戳进行排序,并轻松提取最早和最晚的。
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
use Time::Piece;
# The hash where we'll store our data
my %dates;
# The format of our dates
my $date_format = '%Y-%b-%d %H:%M:%S';
# Read each data item from DATA (or wherever)
while (<DATA>) {
# Remove the newline
chomp;
# Parse the string into a Time::Piece object
my $date = Time::Piece->strptime($_, $date_format);
# Store the object in our hash of arrays
push @{$dates{$date->ymd}}, $date;
}
# Get the list of hash keys sorted by date.
for (sort keys %dates) {
# For each date key...
# Get the sorted list of dates into an array...
my @times = sort { $a->hms cmp $b->hms } @{ $dates{$_} };
# And print the first and last elements of the array,
# using the correct format string.
say "begin: ", $times[0]->strftime($date_format);
say "end: ", $times[-1]->strftime($date_format);
}
__DATA__
2021-Oct-11 16:27:39
2021-Oct-11 16:28:10
2021-Oct-11 16:30:47
2021-Oct-11 16:30:47
2021-Oct-12 09:27:03
2021-Oct-12 10:27:03
2021-Oct-12 18:22:15
2021-Oct-13 08:57:16
2021-Oct-13 08:57:37
2021-Oct-13 11:33:25
2021-Oct-13 11:33:25
2021-Nov-08 16:45:17
2021-Nov-08 16:49:10
2021-Nov-08 17:00:50
2021-Nov-08 22:10:24
2021-Nov-09 11:51:35
2021-Nov-09 11:52:40
2021-Nov-09 12:14:39
2021-Nov-09 14:23:10
由于输入是排序的,所以你需要的是:
my ( $prev_line, $prev_d );
while ( my $line = <> ) {
my ( $d ) = split( ' ', $line );
if ( !$prev_line ) {
print "begin: $line";
$prev_d = $d;
}
elsif ( $d ne $prev_d ) {
print "end: $prev_line";
print "begin: $line";
$prev_d = $d;
}
$prev_line = $line;
}
if ( $prev_line ) {
print "end: $prev_line";
}