lilalo
annotate l3text @ 155:8ee5e59f1bd3
Локальное хранение и анализ данных с помощью SQlite
Очень много изменений, касающихся работы с sqlite
и локального использования результатов записи.
Подробнее:
README.l3text
Очень много изменений, касающихся работы с 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/&/&/g; |
igor@155 | 344 $text =~ s/</</g; |
igor@155 | 345 $text =~ s/>/>/g; |
igor@155 | 346 $text =~ s/"/"/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 } |