#
# grepdbg [nn] [-mm] <regular expression>
#
-
# nn - is the day you what to look at: 1 is yesterday, 0 is today
# and is optional if there is only one argument
#
-# -mmm - print the mmm lines before the match. So -10 will print
-# ten lines including the line matching the regular expression.
+# -mmm - print the mmm lines before the match. So -3 will print
+# 4 lines altogether, the 3 lines before the line matching
+# the regular expression.
#
# <regexp> is the regular expression you are searching for,
-# a caseless search is done
+# a caseless search is done. There can be more than one <regexp>
+# a <regexp> preceeded by a '!' is treated as NOT <regexp>. Each
+# <regexp> is implcitly ANDed together.
+#
+# If you specify something that likes a filename and that filename
+# has a .pm on the end of it and it exists then rather than doing
+# the regex match it executes the "main::handle()" function passing
+# it one line at a time.
#
#
require 5.004;
+package main;
+
# search local then perl directories
BEGIN {
# root of directory tree for this system
unshift @INC, "$root/local";
}
-use DXVars;
+use SysVar;
use DXUtil;
use DXLog;
use Julian;
use strict;
-use vars qw(@list $fp $today $string);
+use vars qw(@days $fp $today $string);
+
$fp = DXLog::new('debug', 'dat', 'd');
$today = $fp->unixtoj(time());
my $nolines = 1;
my @prev;
+my @patt;
-for my $arg (@ARGV) {
+foreach my $arg (@ARGV) {
if ($arg =~ /^-/) {
- $arg =~ s/^-//o;
- push @list, $arg;
+ $arg =~ s/^-+//;
+ if ($arg =~ /\?|^he?l?p?/) {
+ usage();
+ exit(0);
+ }
+ $nolines += $arg if $arg =~ /^\d+$/;
} elsif ($arg =~ /^\d+$/) {
- $nolines = $arg;
+ push @days, $arg;
+ } elsif ($arg =~ /\.pm$/) {
+ if (-e $arg) {
+ my $fn = $arg;
+ $fn =~ s/\.pm$//;
+ eval { require $arg};
+ die "requiring $fn failed $@" if $@;
+ die "required $fn does not contain 'sub handle' (check that 'package main;' exists)" unless main->can('handle');
+ } else {
+ die "$arg not found";
+ }
} else {
- $string = $arg;
- last;
+ push @patt, $arg;
}
}
-die "usage: grepdbg [nn] [[-nnn] ..] <regexp>\n" unless $string;
-push @list, "0" unless @list;
-for my $entry (@list) {
+push @patt, '.*' unless @patt;
+
+push @days, "0" unless @days;
+for my $entry (@days) {
my $now = $today->sub($entry);
my $fh = $fp->open($now);
my $line;
+ my $do;
+
+
+ begin() if main->can('begin');
if ($fh) {
while (<$fh>) {
- my $line = $_;
- chomp $line;
- push @prev, $line;
- shift @prev while @prev > $nolines;
- if ($line =~ m{$string}io) {
- for (@prev) {
- s/([\x00-\x1f\x7f-\xff])/sprintf("\\x%02X", ord($1))/eg;
- my ($t, $l) = split /\^/, $_, 2;
- print atime($t), ' ', $l, "\n";
- }
- @prev = ();
+ if (main->can('handle')) {
+ handle($_);
+ } else {
+ process($_);
}
}
$fp->close();
}
+ end() if main->can('end');
+}
+
+total() if main->can('total');
+exit 0;
+
+sub process
+{
+ my $line = shift;
+ chomp $line;
+ push @prev, $line;
+ shift @prev while @prev > $nolines;
+ my $flag = 0;
+ foreach my $p (@patt) {
+ if ($p =~ /^!/) {
+ my $r = substr $p, 1;
+ last if $line =~ m{$r}i;
+ } else {
+ last unless $line =~ m{$p}i;
+ }
+ ++$flag;
+ }
+ if ($flag == @patt) {
+ for (@prev) {
+ s/([\x00-\x1f\x7f-\xff])/sprintf("\\x%02X", ord($1))/eg;
+ my ($t, $l) = split /\^/, $_, 2;
+ print atime($t), ' ', $l, "\n";
+ }
+ print "------------------\n" if $nolines > 1;
+ @prev = ();
+ }
+}
+
+sub usage
+{
+ print << "XXX";
+
+ usage: grepdbg [nn days before] [-nnn lines before] [<perl filter module>] [<regexp>|!<regexp>]...
+
+ You can have more than one <regexp> with an implicit 'and' between them. All
+ <regexes> are caseless. It's recommended to put 'not' (!<regex>) first in any list.
+ Don't forget that you are doing this in a shell and you may need to quote your
+ <regex>s.
+
+ grepdbg with no arguments will simply list the current debug log with the timestamp
+ for each line decoded into a human readable form.
+
+ grepdbg | less
+
+ is a handy way of scrolling through the debug log.
+
+ grepdbg -2 progress
+
+ will display any line containing 'progress' and also the two lines before that.
+
+ You can install your own content and display arrangement (useful for filtering data
+ in some complicated way). You call it like this (assuming it is called 'filter.pm').
+ This is what is meant by <perl filter module>.
+
+ grepdbg filter.pm
+
+ All the other arguments to grepdbg are available to limit the input to your filter.
+ If you want them.
+
+ The filter module MUST contain at least:
+
+ package main;
+
+ sub handle
+ {
+ your code goes here
+ }
+ 1;
+
+ It can also have a 'sub begin {...}' and / or 'sub end {...}' which are executed
+ immediately after opening a logfile and then just before closing it, respectively.
+
+ You can also add a 'sub total {...}' which executes after the last line is
+ printed and grepdbg exits.
+
+ Read the code of this program and copy'n'paste the 'sub
+ process' code into a new file. Then change 'sub process'
+ to 'sub handle'. Add the line 'package main;' at the beginning
+ of the file and a line '1;' at the end and then modify it to
+ your requirements...
+
+XXX
}
-exit(0);