Perl 解析文件中的“文件”;错误";,将找到的记录的索引作为键写入新文件。使用密钥文件搜索第一个文件中的记录
[upate:这里有我没有看到的Perl文件操作函数/方法吗?] 我在面试时遇到了一道Perl问题。我相信我给出了问题的答案,但不是他们想要的“脑筋急转弯”的答案。因此,我重新学习了Perl来编写代码,并与他们的答案进行比较测试。我的Perl不是很强,所以我不确定我是否以最佳方式编写了他们的解决方案。我希望对他们公平(我仍然认为我的解决方案的速度是指数级的。) 问题:扫描包含多行日志项的日志文件Perl 解析文件中的“文件”;错误";,将找到的记录的索引作为键写入新文件。使用密钥文件搜索第一个文件中的记录,perl,file,logging,hash,big-o,Perl,File,Logging,Hash,Big O,[upate:这里有我没有看到的Perl文件操作函数/方法吗?] 我在面试时遇到了一道Perl问题。我相信我给出了问题的答案,但不是他们想要的“脑筋急转弯”的答案。因此,我重新学习了Perl来编写代码,并与他们的答案进行比较测试。我的Perl不是很强,所以我不确定我是否以最佳方式编写了他们的解决方案。我希望对他们公平(我仍然认为我的解决方案的速度是指数级的。) 问题:扫描包含多行日志项的日志文件 01 BEGIN 01 some text 02 BEGIN 01 more Text 01
01 BEGIN
01 some text
02 BEGIN
01 more Text
01 END
02 other text
02 END
03 BEGIN
03 even more text
03 ERROR
...
找到错误记录并将整个记录写入新文件。上述例子将产生:
03 BEGIN
03 even more text
03 ERROR
在新文件中。以“end”结尾的日志条目/记录不在新文件中
限制:您不能一次读取整个文件。由于文件大小和内存限制,您必须一次读取一行
他们的解决办法:
他们特别不希望将密钥文件作为约束完全读入内存。
每次出现“错误”时,都要扫描日志文件。如果找到,则将“索引”编号03作为密钥写入新文件。接下来将使用此密钥文件
03
将与日志文件中的索引号匹配的日志文件重新扫描到密钥文件中的密钥
我陷入困境,需要帮助的是如何更有效地解决问题
我一次读取一行中的第一个日志文件,以获取日志条目索引。
然后,我一次读取一行密钥文件以获取密钥。
然后我对索引和键进行了“eq”
if ( $_[0] eq $key )
{
return 1;
}
在我看来,这是低效的。这将读取整个原始日志文件两次
my %queues;
my @logLines; # queue to hold lines in order for later write if needed
push @logLines, $line;
$queues{ $index } = [@logLines];
如果读取了“END”,那么我就删除了队列,因为我不需要将其写出来
如果读取了“ERROR”,那么我写出了队列的内容,删除了队列
然后删除队列的哈希项
结果是“错误”块以正确的顺序写入文件。
无需写入或重新匹配密钥文件。
无需对最终文件进行排序
针对10000个日志记录文件(约80000行)
我认为我的代码会:
A. Be so much faster
B. Be the same no matter the error rate.
这里有成年人想计算这些的O(n)吗
谢谢大家
随着密钥数量的增加,这会对日志文件中的每一行读取密钥文件X次,由于错误率的原因,将一个日志行与多个密钥进行匹配所需的时间会快速增长
不,它实际上只需要两次通过。一次识别错误块。将它们保存在散列中。然后,在第二个过程中,检查散列中是否存在密钥,以决定是否保留块
我猜问题在于需要保留的行数可能是无限的
以下假设您可以在内存中保留具有错误
状态代码的任务的查找表。如果出现错误的任务数量也可能很大,则可以使用磁盘上的键值存储(例如Berkeley DB、memcache
等)替换简单的哈希查找表:
如果是可能的话,我会考虑将行插入到SQLite数据库中,并用< /代码>和<>代码>按打印<适当的<代码>组。< /P>重叠<代码>开始和<代码>结束<代码>标记…这是否意味着它们标记了“部分”,但这些部分可以嵌套?如果这些确实是分区,那么任何一个分区可以获得多大的信息?使用哈希确实可以加快速度。但他们的解决方案是不使用%散列。我曾多次明确指出,使用散列可以加快进程。他们反驳说不需要这样做。一次读取一行文件而不保存行是可以的。我猜他们是想做perl1>perl2>perl3的事情。或者他们想在微服务中运行一些不需要散列的东西。在这一点上,我们有一个模糊的问题描述,没有真正的约束规范,所以我觉得进一步的推测是没有用的。最重要的是,代码中存在浪费性的结构,例如,
$queues{$index}=[@logLines]代码>这让我怀疑你可能误解了他们所说的和/或我所说的和/或我不理解你所说的。我不是在评判。我正在解释为什么你的问题应该以“太宽:Pl”结尾
A. Be so much faster
B. Be the same no matter the error rate.
#!/usr/bin/env perl
use strict;
use warnings;
use autouse Carp => 'croak';
run($ARGV[0]);
sub run {
my $logfile = shift;
my $failed_tasks = identify_failed_tasks($logfile);
print_failed_tasks($logfile, $failed_tasks);
}
sub identify_failed_tasks {
my $logfile = shift;
open my $in, '<', $logfile
or croak "Failed to open '$logfile' for reading: $!";
my %failed_tasks;
while (my $line = <$in>) {
last unless $line =~ /\S/;
my ($id, $status) = split ' ', $line, 3;
next unless $status eq 'ERROR';
$failed_tasks{$id} = undef;
}
close $in
or croak "Failed to close '$logfile': $!";
return \%failed_tasks;
}
sub print_failed_tasks {
my $logfile = shift;
my $failed_tasks = shift;
open my $in, '<', $logfile
or croak "Failed to open '$logfile' for reading: $!";
while (my $line = <$in>) {
last unless $line =~ /\S/;
my ($id) = ($line =~ /^(\S+)/);
next unless exists $failed_tasks->{$id};
print $line;
}
close $in
or croak "Failed to close '$logfile': $!";
return;
}