lilalo

annotate l3text @ 155:8ee5e59f1bd3

Локальное хранение и анализ данных с помощью SQlite

Очень много изменений, касающихся работы с sqlite
и локального использования результатов записи.
Подробнее:
README.l3text
author Igor Chubin <igor@chub.in>
date Tue Mar 16 20:05:30 2010 +0200 (2010-03-16)
parents
children
rev   line source
igor@155 1 #!/usr/bin/perl -w
igor@155 2
igor@155 3 use POSIX qw(strftime);
igor@155 4 use lib '/etc/lilalo';
igor@155 5 use l3config;
igor@155 6 use utf8;
igor@155 7 use DBI;
igor@155 8 #no warnings;
igor@155 9
igor@155 10 our @Fields=qw/id time prompt cline output err last_command tab diff l3cd/;
igor@155 11 our $Fields=join(", ",@Fields);
igor@155 12 our $db;
igor@155 13
igor@155 14 =cut
igor@155 15 Множество команд, с которыми выполняется операция,
igor@155 16 определяется текущим контекстом и текущей строкой,
igor@155 17 а также параметрами:
igor@155 18 * фильтр;
igor@155 19 * регулярное выражение;
igor@155 20 * интервал.
igor@155 21 =cut
igor@155 22 our $Filter;
igor@155 23 our $Grep;
igor@155 24 our $Interval;
igor@155 25 our $Command;
igor@155 26
igor@155 27 # Если мы используем режим -f, то в этой переменной запоминается
igor@155 28 # до какой точки мы дошли
igor@155 29 our $Follow=0;
igor@155 30
igor@155 31 our $Context;
igor@155 32
igor@155 33 our @Commands = qw/head tail cat history/;
igor@155 34
igor@155 35 sub main();
igor@155 36 sub connect_database();
igor@155 37
igor@155 38 main();
igor@155 39
igor@155 40 sub main()
igor@155 41 {
igor@155 42 $| = 1;
igor@155 43
igor@155 44 init_config_without_command_line_processing();
igor@155 45 $Context=$Config{l3cd};
igor@155 46 connect_database();
igor@155 47 # Обработка всех grep'ов
igor@155 48 $Grep="";
igor@155 49 my $i=0;
igor@155 50 my $arg;
igor@155 51 my @argv=();
igor@155 52 while ($i<=$#ARGV) {
igor@155 53 $arg=$ARGV[$i];
igor@155 54 #print "arg=$arg\n";
igor@155 55 if ($arg eq "grep") {
igor@155 56 my $grep_keys="";
igor@155 57 my $grep_regexp="";
igor@155 58 $i++;
igor@155 59 while(defined ($ARGV[$i]) and $ARGV[$i] =~ /^-/) {
igor@155 60 $grep_keys .= " ".$ARGV[$i];
igor@155 61 $i++;
igor@155 62 }
igor@155 63 if (defined($ARGV[$i])) {
igor@155 64 $grep_regexp = $ARGV[$i];
igor@155 65 $i++;
igor@155 66 }
igor@155 67 else {
igor@155 68 die "ERROR: grep argument is not specified";
igor@155 69 }
igor@155 70 $Grep .= grep_options($grep_regexp,$grep_keys);
igor@155 71 }
igor@155 72 else {
igor@155 73 $i++;
igor@155 74 push(@new_argv,$arg);
igor@155 75 }
igor@155 76 }
igor@155 77 @argv=@new_argv;
igor@155 78
igor@155 79 if (grep(/^-f$/, @argv)) {
igor@155 80 $follow=1;
igor@155 81 }
igor@155 82 if (grep(/^history$/, @argv)) {
igor@155 83 my $interval=$argv[0]||"%";
igor@155 84 $interval="%" if $interval eq "history";
igor@155 85 my $exit=0;
igor@155 86 while (not $exit) {
igor@155 87 print_commands(select_interval($interval, $Grep));
igor@155 88 if (not $follow) {
igor@155 89 $exit=1;
igor@155 90 } else {
igor@155 91 sleep(1);
igor@155 92 }
igor@155 93 }
igor@155 94 } else {
igor@155 95 my $exit=0;
igor@155 96 while (not $exit) {
igor@155 97 print_all(select_interval($argv[0]||"%", $Grep));
igor@155 98 if (not $follow) {
igor@155 99 $exit=1;
igor@155 100 } else {
igor@155 101 sleep(1);
igor@155 102 }
igor@155 103 }
igor@155 104 }
igor@155 105 #print_all(select_by_cline("*privet*"));
igor@155 106 }
igor@155 107
igor@155 108 sub connect_database()
igor@155 109 {
igor@155 110 $db = DBI->connect("dbi:SQLite:".$Config{cache_sqlite}, "", "",
igor@155 111 {RaiseError => 1, AutoCommit => 1});
igor@155 112 $db->func('regexp', 2, sub {
igor@155 113 my ($regex, $string) = @_;
igor@155 114 return $string =~ /$regex/;
igor@155 115 }, 'create_function');
igor@155 116 }
igor@155 117
igor@155 118 sub select_all() {
igor@155 119 $l3cd=$Config{l3cd};
igor@155 120 return $db->selectall_arrayref("SELECT $Fields FROM commands WHERE l3cd='$l3cd'");
igor@155 121 }
igor@155 122
igor@155 123 sub select_last_n($) {
igor@155 124 my $last=$_[0];
igor@155 125 $count = $db->selectall_arrayref("SELECT COUNT(*) FROM commands");
igor@155 126 my $offset=$$count[0][0]-$last;
igor@155 127 return $db->selectall_arrayref("SELECT $Fields FROM commands LIMIT $last OFFSET $offset");
igor@155 128 }
igor@155 129
igor@155 130 sub select_interval($) {
igor@155 131 my $interval = shift;
igor@155 132 my $grep = shift;
igor@155 133
igor@155 134 my $q; # Рабочая переменная для запросов
igor@155 135 # %
igor@155 136 $interval='1,$' if ($interval eq "%");
igor@155 137 # return $db->selectall_arrayref(
igor@155 138 # "SELECT $Fields FROM commands WHERE l3cd='$Context'");
igor@155 139
igor@155 140 # Вычисляем номера начальной и конечной строки
igor@155 141 # на основе интервала
igor@155 142 my ($start,$stop);
igor@155 143 my ($start_n, $stop_n, $curr_n) = ("","",""); # номера начальной и конечной строк
igor@155 144 if ($interval =~ /,/) {
igor@155 145 ($start,$stop) = split(/,/,$interval);
igor@155 146 }
igor@155 147 else {
igor@155 148 $start = $interval;
igor@155 149 $stop = $interval;
igor@155 150 }
igor@155 151
igor@155 152 $q = $db->selectall_arrayref("SELECT COUNT(*) FROM commands");
igor@155 153 my $count = $$q[0][0];
igor@155 154
igor@155 155 # Номер текущей строки
igor@155 156 # По умолчанию текущая строка указывает на последнюю
igor@155 157 $curr_n = $count;
igor@155 158 #$curr_n = 2;
igor@155 159
igor@155 160 if ($start =~ /^[0-9]*$/) { $start_n = $start; }
igor@155 161 if ($stop =~ /^[0-9]*$/) { $stop_n = $stop; }
igor@155 162 if ($start =~ /^-[0-9]*$/) { $start_n = $curr_n + $start; }
igor@155 163 if ($stop =~ /^-[0-9]*$/) { $stop_n = $curr_n + $stop; }
igor@155 164 if ($start =~ /^\+[0-9]*$/) { $start_n = $curr_n + $start; }
igor@155 165 if ($stop =~ /^\+[0-9]*$/) { $stop_n = $curr_n + $stop; }
igor@155 166 if ($start eq '.') { $start_n = $curr_n; }
igor@155 167 if ($stop eq '.') { $stop_n = $curr_n; }
igor@155 168 if ($start eq '$') { $start_n = $count; }
igor@155 169 if ($stop eq '$') { $stop_n = $count; }
igor@155 170 if ($start =~ m@^/(.*)/@ ) {
igor@155 171 $q = $db->selectall_arrayref(
igor@155 172 "SELECT id FROM commands WHERE cline REGEXP '$1' LIMIT 1");
igor@155 173 $start_n=$$q[0][0];
igor@155 174 }
igor@155 175 if ($stop =~ m@^/(.*)/@ ) {
igor@155 176 $q = $db->selectall_arrayref(
igor@155 177 "SELECT id FROM commands
igor@155 178 WHERE cline REGEXP '$1'
igor@155 179 AND (id >= $start_n) LIMIT 1");
igor@155 180 $stop_n=$$q[0][0];
igor@155 181 }
igor@155 182 if ($start =~ m@^o/(.*)/@ ) {
igor@155 183 $q = $db->selectall_arrayref(
igor@155 184 "SELECT id FROM commands WHERE output REGEXP '$1' LIMIT 1");
igor@155 185 $start_n=$$q[0][0];
igor@155 186 }
igor@155 187 if ($stop =~ m@^o/(.*)/@ && $start_n) {
igor@155 188 $q = $db->selectall_arrayref(
igor@155 189 "SELECT id FROM commands
igor@155 190 WHERE output REGEXP '$1' AND (id >= $start_n) LIMIT 1");
igor@155 191 $stop_n=$$q[0][0];
igor@155 192 }
igor@155 193
igor@155 194 if (not $start_n or not $stop_n) {return ""};
igor@155 195
igor@155 196 $stop_n = $count if $count < $stop_n;
igor@155 197 $start_n =1 if 1 > $start_n;
igor@155 198
igor@155 199 my $offset=$start_n-1;
igor@155 200 my $limit = $stop_n - $offset;
igor@155 201
igor@155 202 my $pre_follow=$Follow;
igor@155 203 $q = $db->selectall_arrayref(
igor@155 204 "SELECT id FROM commands
igor@155 205 WHERE ((id>=$start_n AND id<=$stop_n AND id>$pre_follow) $grep)
igor@155 206 ORDER BY id DESC");
igor@155 207 $Follow = $$q[0][0] if $$q[0][0];
igor@155 208 return $db->selectall_arrayref(
igor@155 209 "SELECT $Fields FROM commands
igor@155 210 WHERE ((id>=$start_n AND id<=$stop_n AND id>$pre_follow) $grep)");
igor@155 211 }
igor@155 212
igor@155 213 sub grep_options($$) {
igor@155 214 =cut
igor@155 215 -c ищем только в комадной строке # по умолчанию
igor@155 216 -o ищем только в выводе
igor@155 217 -f ищем и там, и там
igor@155 218 -v инверсия
igor@155 219 =cut
igor@155 220 my $regexp=shift; return "" if $regexp eq '';
igor@155 221 my $options=shift;
igor@155 222 my @options = split //, $options;
igor@155 223 my $not = "";
igor@155 224 $not = "NOT" if grep(/v/,@options);
igor@155 225
igor@155 226 my $grep ="";
igor@155 227 if (grep(/f/,@options)) {
igor@155 228 $grep = "AND $not ((cline REGEXP '$regexp') OR (output REGEXP '$regexp'))";
igor@155 229 }
igor@155 230 elsif (grep(/o/,@options)) {
igor@155 231 $grep = "AND $not (output REGEXP '$regexp')";
igor@155 232 }
igor@155 233 elsif (1 || grep(/c/,@options)) {
igor@155 234 $grep = "AND $not (cline REGEXP '$regexp')";
igor@155 235 }
igor@155 236
igor@155 237 return $grep;
igor@155 238 }
igor@155 239
igor@155 240 sub select_by_cline($) {
igor@155 241 my $cline = $_[0];
igor@155 242 return $db->selectall_arrayref("SELECT $Fields FROM commands WHERE cline GLOB '$cline'");
igor@155 243 }
igor@155 244
igor@155 245 sub print_commands($)
igor@155 246 {
igor@155 247 my @fields=@Fields;
igor@155 248 my $fields=join(", ",@fields);
igor@155 249 my $all=$_[0];
igor@155 250 foreach my $row (@$all) {
igor@155 251 my $cl; #Каждая строка
igor@155 252 my $i=0;
igor@155 253 for my $f (@fields) {
igor@155 254 $cl->{$fields[$i]}=$$row[$i];
igor@155 255 $i++;
igor@155 256 }
igor@155 257 print $cl->{id}." ".strdequot($cl->{cline})."\n";
igor@155 258 }
igor@155 259 }
igor@155 260 sub print_all($) {
igor@155 261 my @fields=@Fields;
igor@155 262 my $fields=join(", ",@fields);
igor@155 263 my $all=$_[0];
igor@155 264 my $prev_cl; # Предыдущая строка
igor@155 265 my $tab_seq; # Номер в табуляционной последовательности
igor@155 266 foreach my $row (@$all) {
igor@155 267 my $cl; #Каждая строка
igor@155 268 my @anchor; #Начальная строка, якорь, по которому привязывается команда
igor@155 269 my $res=""; #Буфер, в который выводится результат вывода каждой строки
igor@155 270 $i=0;
igor@155 271 for my $f (@fields) {
igor@155 272 $cl->{$fields[$i]}=$$row[$i];
igor@155 273 $i++;
igor@155 274 }
igor@155 275 next if ($Config{"skip_empty"} =~ /^y/i && $cl->{"cline"} =~ /^\s*$/ )
igor@155 276 || ($Config{"skip_wrong"} =~ /^y/i && $cl->{"err"} != 0)
igor@155 277 || ($Config{"skip_interrupted"} =~ /^y/i && $cl->{"err"} == 130);
igor@155 278
igor@155 279 # Время
igor@155 280 # Добавляем спереди 0 для удобочитаемости
igor@155 281 my ($sec,$min,$hour,$day,$mon,$year,$wday,$yday,$isdst) = localtime($cl->{time});
igor@155 282 $min = "0".$min if $min =~ /^.$/;
igor@155 283 $hour = "0".$hour if $hour =~ /^.$/;
igor@155 284 $sec = "0".$sec if $sec =~ /^.$/;
igor@155 285
igor@155 286 if ($Config{"show_time"} =~ /^y/i) {
igor@155 287 push @anchor,"$hour:$min:$sec ";
igor@155 288 }
igor@155 289
igor@155 290 if ($cl->{"err"}) {
igor@155 291 push @anchor, "err=".$cl->{'err'};
igor@155 292 }
igor@155 293 if ($cl->{"tab"}) {
igor@155 294 push @anchor, "tab=".$cl->{'tab'};
igor@155 295 }
igor@155 296 $res.="#=".join("",@anchor)."\n";
igor@155 297 $res.=$cl->{prompt}.strdequot($cl->{cline})."\n";
igor@155 298
igor@155 299 my $output = ""; # фомируем вывод команды
igor@155 300 my $last_command = $cl->{"last_command"};
igor@155 301 if (!( $Config{"suppress_editors"} =~ /^y/i
igor@155 302 && grep ($_ eq $last_command, @{$Config{"editors"}})
igor@155 303 || $Config{"suppress_pagers"} =~ /^y/i
igor@155 304 && grep ($_ eq $last_command, @{$Config{"pagers"}})
igor@155 305 || $Config{"suppress_terminal"}=~ /^y/i
igor@155 306 && grep ($_ eq $last_command, @{$Config{"terminal"}})
igor@155 307 )) {
igor@155 308 $output = strdequot($cl->{output});
igor@155 309
igor@155 310 # Вырезаем слишком длинные выводы
igor@155 311 my @lines = split '\n', $output;
igor@155 312 if (!$Config{"command_id"}
igor@155 313 && ( $Config{"head_lines"} || $Config{"tail_lines"})
igor@155 314 && $#lines > $Config{"head_lines"} + $Config{"tail_lines"}) {
igor@155 315 $output="";
igor@155 316 for (my $i=0; $i<= $#lines && $i < $Config{"head_lines"}; $i++) {
igor@155 317 $output .= $lines[$i]."\n";
igor@155 318 }
igor@155 319 $output .= $Config{"skip_text"}."\n";
igor@155 320
igor@155 321 my $start_line=$#lines-$Config{"tail_lines"}+1;
igor@155 322 for (my $i=$start_line; $i<= $#lines; $i++) {
igor@155 323 $output .= $lines[$i]."\n";
igor@155 324 }
igor@155 325 }
igor@155 326 }
igor@155 327 $res.=$output;
igor@155 328 if ( $Config{"show_diffs"} =~ /^y/i && $cl->{"diff"}) {
igor@155 329 $res.= $cl->{"diff"}
igor@155 330 }
igor@155 331 #open(OUTPUT, '|sendxmpp nata_samoylenko@jabber.ru');
igor@155 332 #print OUTPUT $res;
igor@155 333 #close(OUTPUT);
igor@155 334 print $res;
igor@155 335 $res="";
igor@155 336 $prev_cl=$cl;
igor@155 337 }
igor@155 338 }
igor@155 339
igor@155 340 sub strdequot($)
igor@155 341 {
igor@155 342 my $text = join "", @_;
igor@155 343 $text =~ s/&amp;/&/g;
igor@155 344 $text =~ s/&lt;/</g;
igor@155 345 $text =~ s/&gt;/>/g;
igor@155 346 $text =~ s/&quot;/"/g;
igor@155 347 return $text;
igor@155 348 }
igor@155 349
igor@155 350 sub show_usage()
igor@155 351 {
igor@155 352 print <<EOF;
igor@155 353 Usage:
igor@155 354 l3 [INTERVAL] [grep [KEYS] REGEXP] [filter [KEYS] FILTER] [COMMAND [KEYS]]
igor@155 355
igor@155 356 Commands:
igor@155 357 history
igor@155 358 tail
igor@155 359 head
igor@155 360 cat (default)
igor@155 361
igor@155 362 If COMMAND is not specified, cat assumed.
igor@155 363
igor@155 364 EOF
igor@155 365 }