perl逻辑请求的IO场景

时间:2015-04-12 03:28:21

标签: perl

我需要帮助构建以下场景的逻辑。

我正在使用Perl来读取2个具有4和2个元素的文件,如下所示。我需要从File1读取每一行,并比较两个文件中是否存在code。 如果两个文件中都存在code,我需要显示file1的所有行元素及其description。你能分享一下你的想法吗?

File1中:

Testname, code, date, file
Test1, 4, 4/11/15, /tmp
Test2, 2, 4/11/15, /log
Test3, 1, 4/11/15, /log

文件2:

Code: description
1: Generic user error
2: Error with file location
3: File not found
4: Syntax error

2 个答案:

答案 0 :(得分:0)

这是一个有效的解决方案:

#!/usr/bin/perl

use strict;
use warnings;
use utf8;

## read file2 first
my $fh2;
open($fh2, '<', 'file2' ) || die("error: could not open file2: $!");
my $header2 = <$fh2>;
chomp($header2);
my $names2 = split(': ',$header2);
my $descriptionMap = {};
while (my $line = <$fh2>) {
    chomp($line);
    my $fields = [split(': ',$line)];
    $descriptionMap->{$fields->[0]} = $fields->[1];
} ## end while
close($fh2);

## run through error list from file1 and print out all error info, plus description from file2 (if found)
my $fh1;
open($fh1, '<', 'file1' ) || die("error: could not open file1: $!");
my $header1 = <$fh1>;
chomp($header1);
my $names1 = [split(', ',$header1)];
while (my $line = <$fh1>) {
    ## parse
    chomp($line);
    my $fields = [split(', ',$line)];
    my $error = {};
    @$error{@$names1} = @$fields; ## hash slice assignment
    ## get description
    my $description = exists($descriptionMap->{$error->{'code'}}) ? $descriptionMap->{$error->{'code'}} : '(not found)';
    ## output
    print($error->{'Testname'},',',$error->{'code'},',',$error->{'date'},',',$error->{'file'},',',$description,"\n");
} ## end while
close($fh1);

exit 0;

输出:

Test1,4,4/11/15,/tmp,Syntax error
Test2,2,4/11/15,/log,Error with file location
Test3,1,4/11/15,/log,Generic user error

它首先在file2中读取一个键入代码的散列,其值为描述。接下来,它读取file1,并为每个错误打印出其信息,并在file2哈希上查找以获取描述。

答案 1 :(得分:0)

如果您使用Perl读取两个文件,您肯定必须有代码来表明我们可以帮助您。如果您还没有编写任何代码,那么您不清楚为什么要使用某种特定语言作为最终目的。如果没有帮助您完成工作的代码,最好从描述如何解决问题开始。

您可以首先将file2读入数据容器,以便轻松进行代码查找。如果代码编号是稀疏分布的,您可能会使用哈希,其中键是代码编号,值是代码&#39;说明。如果数字密集分布,您可以使用数组作为结构,其中索引表示代码编号,值是代码的描述。既然我们不知道这个问题的答案,我们应该探索一种在任何一种情况下都能令人满意地工作的一般解决方案;建议使用散列。

下一步是迭代file1中的行,使用正则表达式或splitText::CSV从行中提取代码,然后使用用于在代码引用哈希中执行查找的代码。

以下是该策略的示例实现:

open my $f2, '<', 'file2' or die $!;
my %codes = map { m/^(\d+):\s*(.+)$/ ? ($1,$2) : () } <$f2>;

open my $f1, '<', 'file1' or die $!;
while( <$f1> ) {
    next unless m/^[^,]+,\s*(\d+),/;
    exists $codes{$1} && do {
        chomp;
        print "$_ => $codes{$1}\n";
    };
}

因此,在该代码的第一部分中,我们打开file2,并将其行提取到名为%codes的哈希中。哈希中的键是数字代码,值是文本描述。

在第二个段中,我们遍历file1行,再次提取代码。我们使用该代码来查找代码的含义。如果查找无法找到意义,我们继续前进。否则,我们继续打印file1中的行以及file2中代码的含义。

它产生的输出是:

Test1, 4, 4/11/15, /tmp => Syntax error
Test2, 2, 4/11/15, /log => Error with file location
Test3, 1, 4/11/15, /log => Generic user error

在我看来,即使找不到代码,打印某些东西可能会更好。如果这比你更好,你可以改变第二个代码块,如下所示:

open my $f1, '<', 'file1' or die $!;
while( <$f1> ) {
    next unless m/^[^,]+,\s*(\d+),/;
    chomp;
    print "$_ => ", exists $codes{$1} ? "$codes{$1}\n" : "UNKNOWN CODE\n"
}   

这两段代码的不同之处在于,第一段代码会跳过file1file2中未找到匹配代码的任何行。这似乎符合您问题中提供的目标的描述。第二个代码段会打印file1中包含代码的每一行,对于那些从file2找不到匹配代码的行,响应&#34; UNKNOWN CODE& #34;打印代替代码说明。