MattJ83 said:
Problem is, your code, as posted, relies on a database we don't know
about, and don't really want to set up anyway. So we can't run the
program, even if we wanted to. Also, you can put your data in your
program, after a __DATA__ literal, and read it with the predefined
DATA filehandle. perldoc perldata for more on this (see: "Special
Literals").
#!/usr/central/bin/perl
use strict;
#use warnings;
You should uncomment this line. If you don't know how to get rid of
the warnings it produces, then ask here, and we can help. But with it
off, you're basically asking us to help you find problems that
warnings can uncover for you. In other words, you're communicating to
us (whether you mean to or not) that our time is less important than
your computers'.
But, we don't have a database set up. So this makes it too hard to
use. Anyway, you just need to replace your database inserts with
print statements to make it easy to use.
my @filenames= </home/username/logs/*.log>;
foreach my $filename (@filenames) {
open my $LOG, '<', $filename or die "can't open $filename: $!\n";
while (<$LOG>) {
if (/updates table/) {
my $info = $_;
{
while (<$LOG>) {
This right here is, well, not to put too fine a point on it, dumb.
You already have a loop over the data. Logically, it's confusing to
start a new loop inside the old one. The usual problem is that when
the next iteration of the outer while() begins, the default assumption
is that it will read the next line after the previous iteration.
Putting another while loop inside it destroys that assumption, and
confuses debuggers to no end. This is very bad style; if you worked
for me, I wouldn't accept it, because the next person to look at your
code would be horribly confused.
Because of the way you've done it, you won't see that effect, but it's
more of an accident than anything else. You definitely should not use
this anywhere else; most of the people responding to you are trying to
communicate that this is a bad and confusing idea.
You don't need to start a brand-new while loop anyway; what your code
says is that you only look for "elapsed" after you find "updates
table", and you only look for "conflicting" or "FASTSEARCH" after you
find "elapsed". If this is the case, you can just do something like:
#/usr/bin/perl
use warnings;
use strict;
my ($info, $elapsed1, $fast, $elapsed2);
while(<DATA>) {
chomp;
if (/updates table/) {
print "found updates: [$_]\n";
$info = $_;
}
if (/elapsed/) {
print "found elapsed: [$_]... ";
if ($fast) {
print "setting elapsed2\n";
$elapsed2 = $_;
last;
} elsif ($info) {
print "setting elapsed1\n";
$elapsed1 = $_;
}
}
if (/conflicting|FASTSEARCH/) {
print "found fast: [$_]\n";
$fast = $_;
}
}
# do db stuff here for real
print "info: [$info] fast: [$fast] ".
"elapsed1: [$elapsed1] elapsed2: [$elapsed2]\n";
__DATA__
Text updates table text
text
text elapsed text
text
FASTSEARCH text text
text elapsed
text
__END__
Notice how I only loop over it once. Each time I find a line I might
be interested in, I check to see if I really am-- in the case of
finding "elapsed", you may want to set $elapsed1 or $elapsed2, so you
have to check if $fast or $info are set to determine which one to set.
$dbh->do("insert into LOGS values ('$filename', '$info', '$elapsed1',
'$fast', '$elapsed2')")
or die ("inserting data failure: $!\n");
Ugh, don't do that. Let DBI escape all the values for you. What if,
for instance, $filename contained the string
a', 'b', 'c', 'd', 'e'); delete from LOGS;
? Then your statement would look like:
$dbh->do("insert into LOGS values ('a', 'b', 'c', 'd', 'e'); delete from LOGS");
That's only the easiest way to screw you up; there are far nastier and
subtler ways to cause problems. Also, and this is NOT a Perl problem,
but since I'm feeling generous, I'll point it out anyway: you should
always list the columns when you do an insert, because (A) it's easier
to see what's going on when you read the code (you can look at it and
know what goes where) and (B) if the order of the fields ever changes,
you're screwed, and you don't know why.
Instead of trying to put in quote marks yourself, let DBI do it for
you with placeholders:
$dbh->do("INSERT INTO LOG (filename, info, start, fast, end)
VALUES (?, ?, ?, ?, ?)", undef,
$filename, $info, $elapsed1, $fast, $elapsed2);
perldoc DBI, and look for "Placeholders and Bind Values" to learn more.
$dbh->disconnect;
}}}}}}}}}}}}}
Ugh. This is butt-ugly. You can't tell by looking at this line which
brace corresponds to which if or while statement. If you wanted to
change the code later, you'll pretty much have to keep running it
until you get rid of all the syntax errors, instead of reading the
code to see what goes where. And even then, you're likely to put
something in the wrong place.
exit;
.log
Text updates table text
text
text elapsed text
text
FASTSEARCH text text
text elapsed
text
If you make multiple copies of this log file and remove the word
FASTSEARCH from one of the logs - the log will not be placed into the
database.
That's what your code says to do-- if you don't find FASTSEARCH, you
don't get to the part that updates the database. Isn't that what you
wanted? I'm not sure, based on your posts here, that you're entirely
clear on what it is you're trying to do here.
-=Eric