Re: Parsing timestamps
by philcrow (Priest) on Nov 04, 2005 at 15:30 UTC
|
You could do two tests. First test for PASS, then check the time. I find two tests easier than a look ahead/behind scheme.
Phil | [reply] |
|
|
| [reply] [d/l] |
|
|
...or the first might be (if *PASS*\s is always last before the newline, as your data suggests):
while ( <DATA> )
{
print "$_ \n";
if ( $_ =~ /(\*PASS\*)\s$/ )
{
print "\n \$1 is: $1 \n";
}
else
{
print "Not found\n";
}
}
__DATA__
2005-11-04/08:02:14.011 METRIC 00020036-0800093A log :Monitor: CALLER
+Status *PASS*
2005-11-04/08:09:34.712 METRIC 0A475-11B Log :monitor: CALLER Status
+*FAIL*
2005-11-04/08:11:30.924 METRIC 00020036-08000940 log :Monitor: CALLER
+Status *PASS*
2005-11-04/08:12:29.830 METRIC 00020036-08000941 log :Monitor: CALLER
+Status *PASS*
2005-11-04/09:12:28.790 METRIC 00020036-08000943 log :Monitor: CALLER
+Status *PASS*
2005-11-04/09:12:35.869 METRIC 00020036-08000944 log :Monitor: CALLER
+Status *PASS*
output is:
2005-11-04/08:02:14.011 METRIC 00020036-0800093A log :Monitor: CALLER
+Status *PASS*
$1 is: *PASS*
2005-11-04/08:09:34.712 METRIC 0A475-11B Log :monitor: CALLER Status
+*FAIL*
Not found
2005-11-04/08:11:30.924 METRIC 00020036-08000940 log :Monitor: CALLER
+Status *PASS*
$1 is: *PASS*
2005-11-04/08:12:29.830 METRIC 00020036-08000941 log :Monitor: CALLER
+Status *PASS*
$1 is: *PASS*
2005-11-04/09:12:28.790 METRIC 00020036-08000943 log :Monitor: CALLER
+Status *PASS*
$1 is: *PASS*
2005-11-04/09:12:35.869 METRIC 00020036-08000944 log :Monitor: CALLER
+Status *PASS*
$1 is: *PASS*
| [reply] [d/l] [select] |
Re: Parsing timestamps
by duff (Parson) on Nov 04, 2005 at 15:44 UTC
|
Since the time information inside of your files seems to be in a good enough form that you could compare them directly with a string comparison, you could do something like this:
use POSIX qw/strftime/;
# generate a timestamp of 12 hours ago in the same format as the data
+file
$twelve_hours_ago = strftime("%Y-%m-%d/%H:%M:%S",localtime(time-12*360
+0));
while (<FH>) {
next unless /PASS/; # skip the non-PASS entries
my ($date) = /^([^.]+)/; # grab the date up to seconds
next unless $date gt $twelve_hours_ago;
# process the interesting records.
}
Update: I had a numeric comparator where clearly a string comparator is warranted and fixed the problem with the 12 hour ago timestamp. Thanks neilwatson, japhy
Update #2: While I'm thinking about it, note that this solution probably breaks at DST boundaries.
| [reply] [d/l] |
|
|
use POSIX qw/strftime/;
# generate a timestamp of 12 hours ago in the same format as the data
+file
$twelve_hours_ago = strftime("%Y-%m-%d/%H:%M:%S",localtime);
Wouldn't that generate a timestamp of now?
| [reply] [d/l] |
|
|
Apart from the 12-hours-ago problem stated above me, you also need to use the string comparison operators (gt instead of >) here.
| [reply] |
Re: Parsing timestamps
by japhy (Canon) on Nov 04, 2005 at 16:14 UTC
|
A regex to match a time within the past 12 hours is doable, but it's probably not nearly as efficient as doing two passes, one to collect the time (if it's a PASS entry) and one to compare that time. But because I can't back away from a challenge:
use Time::Local;
while (<$file>) {
if (m{
^
(\d\d\d\d) - (\d\d) - (\d\d) # capture y/m/d to $1,$2,$3
/
(\d\d) : (\d\d) : (\d\d) # capture h/m/s to $4,$5,$6
(?(?{
timelocal($6,$5,$4,$3,$2-1,$1-1900) < (time - 12*60*60)
})(?!)) # fail if timestamp is older than 12 hours
.* \*PASS\*
}x) {
# it's an ok line!
}
}
Untested, but should work fine.
| [reply] [d/l] |
Re: Parsing timestamps
by blue_cowdawg (Monsignor) on Nov 04, 2005 at 16:42 UTC
|
#!/usr/bin/perl -w
use strict;
use Date::Manip;
my $now=ParseDate(scalar(localtime()));
my $hours_ago = DateCalc("12 hours ago",$now);
while (my $line=<DATA>){
chomp $line;
my ($timestamp,$metric,$serial,$source,$stuff,$foo,$status,$passfa
+il)
= split(/[\s\t\n]+/,$line);
next unless $passfail eq '*PASS*';
my $date = ParseDate($timestamp);
my $flag=Date_Cmp($hours_ago,$date);
if ( $flag < 0 ) {
printf "%s\n",$line;
}
}
exit(0);
__END__
2005-11-04/08:02:14.011 METRIC 00020036-0800093A log :Monitor: CALLER
+Status *PASS*
2005-11-04/08:11:30.924 METRIC 00020036-08000940 log :Monitor: CALLER
+Status *PASS*
2005-11-04/08:12:29.830 METRIC 00020036-08000941 log :Monitor: CALLER
+Status *PASS*
2005-11-04/09:12:28.790 METRIC 00020036-08000943 log :Monitor: CALLER
+Status *PASS*
2005-11-04/09:12:35.869 METRIC 00020036-08000944 log :Monitor: CALLER
+Status *PASS*
Obviously you'd have to tailor this to fit your needs, but
it is something you can work with...
Peter L. Berghold -- Unix Professional
Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
| [reply] [d/l] |
Re: Parsing timestamps
by neilwatson (Priest) on Nov 04, 2005 at 19:43 UTC
|
Thanks for all of your input. Here is the code snipped I used:
# Timestamp 12 hours ago
my $twelve_hours_ago = strftime("%Y-%m-%d/%H:%M:%S", (localtime(time-$
+hours*3600)));
# Logfile may have been rotated during the past 12 hours. Thus we mus
+t open
# any logfile that is less than 12 hours old.
find(\&wanted, "$logfile");
sub wanted {
# Open loge file if it is less than 12 hours old and the
# correct file name
if ( (stat $_)[9] > time() - (3600 * $hours)
&& m/^log_file/ ) {
# Debugging lines
#print "file: ".$_."\n";
#my $stat = (stat $_)[9];
#print "stat: ".$stat."\n";
#my $twelve = time() - (3600 * $hours);
#print "twelve: ".$twelve."\n";
# End of debugging lines.
open LF, ($_) || die "Cannot open $logfile $!";
while (<LF>){
# Check for PASS log entry
next unless (m/log :Monitor: CALLER Status \*PASS\*/);
# Check timestamp
$date = $1 if (m/^([^.]+)/); # Grab the date up to secon
+ds
next unless $date gt $twelve_hours_ago;
#print "date: ".$date."\n"; # For debugging.
# Count number for passes.
$passcount++;
# Save log line
push @passlogs, $_;
}
}
}
| [reply] [d/l] |
Re: Parsing timestamps
by ambrus (Abbot) on Nov 04, 2005 at 22:02 UTC
|
If you don't need tight performance, I recommend that you use Date::Manip. Here's an example.
use Date::Manip;
$limit = ParseDate("12 hours ago") or die "internal error";
while(<>) {
/^(\S+).*\*PASS\*$/ and Date_Cmp($limit, ParseDate($1)) < 0 or nex
+t;
print "found: $_\n";
}
Update: I see that blue_cowdawg has dome almost the same as me. | [reply] [d/l] |