无法使用Perl从大小为~2GB的文件中读取某些单词的计数
我已经编写了一个Perl程序,它将匹配日志文件中的某些单词,并将结果存储在数据库中。问题是,这个程序可以很好地处理小文件,但不能处理大小为2GB的文件。是否需要更改尺寸或程序无法使用Perl从大小为~2GB的文件中读取某些单词的计数,perl,shell,Perl,Shell,我已经编写了一个Perl程序,它将匹配日志文件中的某些单词,并将结果存储在数据库中。问题是,这个程序可以很好地处理小文件,但不能处理大小为2GB的文件。是否需要更改尺寸或程序 use POSIX qw(strftime); # load module use DBI; open( FILE, "/root/temp.log" ) or die "Unable to open logfile:$!\n"; $count_start = 0; $count_interim = 0; $cou
use POSIX qw(strftime);
# load module
use DBI;
open( FILE, "/root/temp.log" ) or die "Unable to open logfile:$!\n";
$count_start = 0;
$count_interim = 0;
$count_stop = 0;
while (<FILE>) {
@test = <FILE>;
foreach $line (@test) {
if ( $line =~ m/server start/ ) {
#print "yes\n";
$count_start++;
}
elsif ( $line =~ m/server interim-update/ ) {
$count_stop++;
}
elsif ( $line =~ m/server stop/ ) {
$count_interim++;
}
}
print "$count_start\n";
print "$count_stop\n";
print "$count_interim\n";
$now_string = strftime "%b %e %H:%M:%S", localtime;
print $now_string;
# connect
my $dbh = DBI->connect( "DBI:Pg:dbname=postgres;host=localhost",
"postgres", "postgres", { 'RaiseError' => 1 } );
# execute INSERT query
my $rows = $dbh->do(
"insert into radcount (acc,bcc,dcc) Values ('$count_start','$count_stop','$count_interim')"
);
print "$rows row(s) affected\n";
# clean up
$dbh->disconnect();
}
close(LOG);
使用POSIXQW(strftime);
#加载模块
使用DBI;
打开(文件“/root/temp.log”)或死“无法打开日志文件:$!\n”;
$count\u start=0;
$count_中期=0;
$count_stop=0;
而(){
@测试=;
foreach$行(@test){
如果($line=~m/server start/){
#打印“是”\n;
$count_start++;
}
elsif($line=~m/服务器临时更新/){
$count_stop++;
}
elsif($line=~m/server-stop/){
$count_临时++;
}
}
打印“$count\u start\n”;
打印“$count\u stop\n”;
打印“$count\u middial\n”;
$now\u string=strftime“%b%e%H:%M:%S”,localtime;
打印$now\u字符串;
#连接
my$dbh=DBI->connect(“DBI:Pg:dbname=postgres;host=localhost”,
“postgres”、“postgres”、{'RaiseError'=>1});
#执行插入查询
我的$rows=$dbh->do(
“在radcount(acc、bcc、dcc)值中插入(‘$count_开始’、‘$count_停止’、‘$count_中间’)”
);
打印“$行受影响的行\n”;
#清理
$dbh->disconnect();
}
关闭(日志);
这里有几件事-首先,我建议将文件句柄更改为三个arg open-推理
open(我的$fileHandle),这里有几件事-首先,我建议将文件句柄更改为三个arg-open-推理
open(my$fileHandle),我对您的程序有一些评论
- 始终在程序开始时
使用strict
和使用warnings
,并在变量首次使用时使用my
声明变量
- 始终使用词法文件句柄和三参数形式的
open
,并始终检查打开调用的状态
- 您正在使用文件句柄
文件
打开文件,但正在关闭日志
- 您的
while
语句读取文件的第一行并将其丢弃
@test=
尝试将文件的其余部分全部读取到数组中。这就是导致问题的原因
- 您应该连接到数据库一次,并在代码的其余部分使用相同的数据库句柄
- 您应该使用带有占位符的
prepare
语句,并使用execute
- 对于
临时更新
记录,您正在增加$count\u stop
;对于停止
记录,您正在增加$count\u transition
- 核心模块
Time::Piece
提供了一种strftime
方法,而不需要POSIX
这里是你的程序的一个修改来展示这些想法。我还没有设置日志文件和数据库来测试它,但它看起来很好,并且可以编译
use strict;
use warnings;
use Time::Piece;
use DBI;
open my $log, '<', '/root/temp.log' or die "Unable to open log file: $!";
my ($count_start, $count_interim, $count_stop) = (0, 0, 0);
while (<$log>) {
if ( /server start/ ) {
$count_start++;
}
elsif ( /server interim-update/ ) {
$count_interim++;
}
elsif ( /server stop/ ) {
$count_stop++;
}
}
print <<END;
Start: $count_start
Interim: $count_interim
Stop: $count_stop
END
print localtime->strftime("%b %e %H:%M:%S"), "\n";
my $dbh = DBI->connect(
"DBI:Pg:dbname=postgres;host=localhost", "postgres", "postgres",
{ 'RaiseError' => 1 } );
my $insert = $dbh->prepare('INSERT INTO radcount (acc, bcc, dcc) VALUES (?, ?, ?)');
my $rows = $insert->execute($count_start, $count_stop, $count_interim);
printf "%d %s affected\n", $rows, $rows == 1 ? 'row' : 'rows';
使用严格;
使用警告;
使用时间::件;
使用DBI;
打开我的$log,“我对你的程序有一些评论
- 始终在程序开始时
使用strict
和使用warnings
,并在变量首次使用时使用my
声明变量
- 始终使用词法文件句柄和三参数形式的
open
,并始终检查打开调用的状态
- 您正在使用文件句柄
文件
打开文件,但正在关闭日志
- 您的
while
语句读取文件的第一行并将其丢弃
@test=
尝试将文件的其余部分全部读取到数组中。这就是导致问题的原因
- 您应该连接到数据库一次,并在代码的其余部分使用相同的数据库句柄
- 您应该使用带有占位符的
prepare
语句,并使用execute
- 对于
临时更新
记录,您正在增加$count\u stop
;对于停止
记录,您正在增加$count\u transition
- 核心模块
Time::Piece
提供了一种strftime
方法,而不需要POSIX
这里是你的程序的一个修改来展示这些想法。我还没有设置日志文件和数据库来测试它,但它看起来很好,并且可以编译
use strict;
use warnings;
use Time::Piece;
use DBI;
open my $log, '<', '/root/temp.log' or die "Unable to open log file: $!";
my ($count_start, $count_interim, $count_stop) = (0, 0, 0);
while (<$log>) {
if ( /server start/ ) {
$count_start++;
}
elsif ( /server interim-update/ ) {
$count_interim++;
}
elsif ( /server stop/ ) {
$count_stop++;
}
}
print <<END;
Start: $count_start
Interim: $count_interim
Stop: $count_stop
END
print localtime->strftime("%b %e %H:%M:%S"), "\n";
my $dbh = DBI->connect(
"DBI:Pg:dbname=postgres;host=localhost", "postgres", "postgres",
{ 'RaiseError' => 1 } );
my $insert = $dbh->prepare('INSERT INTO radcount (acc, bcc, dcc) VALUES (?, ?, ?)');
my $rows = $insert->execute($count_start, $count_stop, $count_interim);
printf "%d %s affected\n", $rows, $rows == 1 ? 'row' : 'rows';
使用严格;
使用警告;
使用时间::件;
使用DBI;
打开我的$log,'还有,使用strict
和使用warnings
!和使用autodie
!是的,我肯定应该提到这些,谢谢你把它捡起来哦,使用DateTime::TimeZone
可能也是个好主意,我想我不确定autodie
DateTime
…好的。它很有效是的。我想的更多的是认真。另一件不太好的事情是没有[DBI
-placeholder](search.cpan.org/~timb/DBI/DBI.pm#placeholder_和(u Bind)值)我也会考虑这个坏的风格。但是我们应该把它放在这个问题的评论中,而不是你的答案,这很好。也许有一些潜在的诡计(取决于他们对他们存储的数据的期望)。当下一个闰日|秒或DST来临时,没有使用时间模块来处理这类问题。你肯定在这里做出了最明智的评论-在这个问题上把它们扔掉!而且,使用严格的
和使用警告
!和使用autodie
!是的,我肯定应该提到这些,谢谢你的帮助我想我也不太清楚如何使用autodieDateTime
…好吧。它的工作原理是这样的。我是
use strict;
use warnings;
use Time::Piece;
use DBI;
open my $log, '<', '/root/temp.log' or die "Unable to open log file: $!";
my ($count_start, $count_interim, $count_stop) = (0, 0, 0);
while (<$log>) {
if ( /server start/ ) {
$count_start++;
}
elsif ( /server interim-update/ ) {
$count_interim++;
}
elsif ( /server stop/ ) {
$count_stop++;
}
}
print <<END;
Start: $count_start
Interim: $count_interim
Stop: $count_stop
END
print localtime->strftime("%b %e %H:%M:%S"), "\n";
my $dbh = DBI->connect(
"DBI:Pg:dbname=postgres;host=localhost", "postgres", "postgres",
{ 'RaiseError' => 1 } );
my $insert = $dbh->prepare('INSERT INTO radcount (acc, bcc, dcc) VALUES (?, ?, ?)');
my $rows = $insert->execute($count_start, $count_stop, $count_interim);
printf "%d %s affected\n", $rows, $rows == 1 ? 'row' : 'rows';