perl 将弃权CSV文件与包含错误的文件进行比较

92dk7w1h  于 2023-08-06  发布在  Perl
关注(0)|答案(2)|浏览(175)

我需要使用下面的示例waiver.csv构建一个用于工作目的的豁免系统。阶段错误已打印在错误文件中(请参阅下文input.txt)。我需要检查input.txt上的每一行错误与waiver.csv(具有匹配的阶段,过程和块),并附带以下示例输出。我需要有关将错误文件中的错误与waiver.csv文件中的错误进行匹配的帮助。
waiver.csv

#process,#Block,#Stage name,#Waiver owner,#Justification,#Error msg
process1,block1,stage1,Alex,testing,Error: Port 0 does not exist
process1,block1,stage1,Alex,testing,Error: Port 1 does not exist
process1,block1,stage1,Alex,testing,Error: Port a0 does not exist

字符串
错误文件(input.txt):

Stage: stage1
Process: process1
Block: block1

Error: Port 0 does not exist
Error: Port 1 does not exist
Error: Port a0 does not exist
Error: Port a1 does not exist
Error: Port b3 does not exist
Error: Nothing matched for port_list (SEL-005)
Error: Nothing matched for port_list (SEL-005)
Error: Port c5 does not exist
Error: Nothing matched for port_list (SEL-005)
Error: Nothing matched for port_list (SEL-005)


预期输出文件:

WAIVED (3 waiver, 0 errors) - stage1,process1,block1:
    Error: Port 0 does not exist
    Error: Port 1 does not exist
    Error: Port a0 does not exist
    Waiver Owner: Alex
    Justification: testing

FAILED (No waiver, 4 errors) - stage1,process1,block1:
    Error: Nothing matched for port_list (SEL-005)
    Error: Port a1 does not exist
    Error: Port b3 does not exist
    Error: Port c5 does not exist


下面是我正在编写的代码:

#!/usr/bin/perl

use strict;
use warnings;
use Text::CSV;

# Define the file paths
my $input_file = 'input.txt';
my $waiver_file = 'waiver.csv';

# Read the waiver.csv file
my @waiver_msgs;
my $csv = Text::CSV->new({ binary => 1 }) or die "Cannot use CSV: " . Text::CSV->error_diag();
open(my $waiver_fh, '<', $waiver_file) or die "Cannot open $waiver_file: $!";
while (my $row = $csv->getline($waiver_fh)) {
    push @waiver_msgs, $row->[5];  # Assuming error messages are in the 6th column (index 5)
}
close($waiver_fh);

# Read the input.txt file
open(my $input_fh, '<', $input_file) or die "Cannot open $input_file: $!";
while (my $line = <$input_fh>) {
    chomp $line;
    if ($line =~ /^Error: (.+)$/) {
        my $error_msg = $1;
        print "$error_msg\n";
        if (grep { $_ eq $error_msg } @waiver_msgs) {
            print "Error message '$error_msg' is waived.\n";
        } else {
            print "Error message '$error_msg' is not waived.\n";
        }
    }
}
close($input_fh);

lkaoscv7

lkaoscv71#

问题是您解析两个输入文件的方式不同。在读取豁免文件时,将保留Error:前缀。但是,在读入错误文件时,不会保留Error:前缀。这就是你的比较失败的原因。
根据所需的输出,您希望保留Error:。既然是这种情况,您应该更改捕获括号以包含它。变更:

if ($line =~ /^Error: (.+)$/) {

字符串
收件人:

if ($line =~ /^(Error: .+)$/) {


或者,由于要捕获整行,因此不需要捕获括号。您可以简化正则表达式,仅在行首搜索错误字符串,然后将错误消息设置为整行:

if ($line =~ /^Error: /) {
    my $error_msg = $line;

zfycwa2u

zfycwa2u2#

谢谢你的询问-这是一个有趣的问题。
我不知道为什么我想到了一个数据库,其中有一个用于查找的“放弃”表和一个用于处理输入数据的正则表达式,但这就是我的想法。所以你去:

#!/usr/bin/env perl

use 5.032001;
use warnings;

use Data::Dumper;
use DBI;
use English;

# Create a database for the waivers and populate it
    my $dbh=DBI->connect('DBI:SQLite::memory:',q{},q{},{ RaiseError=>1 });
    $dbh->do(<<'_create_table_');
        CREATE TABLE waivers (
            process       TEXT,
            block         TEXT,
            stage         TEXT,
            owner         TEXT,
            justification TEXT,
            error         TEXT,
            UNIQUE (process,block,stage,owner,justification,error) ON CONFLICT IGNORE
            );
_create_table_
    $dbh->do(<<'_insert_waivers_');
        -- Note I added the waiver with owner Eve just for amusement!!
        INSERT INTO waivers (process,block,stage,owner,justification,error)
        VALUES
        ('process1','block1','stage1','Alex','testing','Port 0 does not exist'),
        ('process1','block1','stage1','Eve', 'testing','Port 0 does not exist'),
        ('process1','block1','stage1','Alex','testing','Port 1 does not exist'),
        ('process1','block1','stage1','Alex','testing','Port a0 does not exist');
_insert_waivers_
    # Statement handle to look up "errors"
    my $sth=$dbh->prepare(<<'_select_');
       SELECT * FROM waivers
               WHERE stage   = ?
                 AND process = ?
                 AND block   = ?
                 AND error   = ?;
_select_

    my ($failed,$waived);
    sub stage {
        # Beginning of new stage
        # clear $waived and $failed
        undef $waived;
        undef $failed;
        }; # sub stage:

    sub error {
        # hit the database and see if the error (in its context) is waived or not
        #    by accessing the capture groups
        $sth->execute(@+{qw(stage process block error)});
        unless (my $value_aref=$sth->fetchrow_arrayref) {
            # No waiver
            $failed->{$+{error}}++;
            }
        else {
            # One or more waivers found
            my $field_aref=$sth->{NAME};
            do {
                my %_h;
                @_h{@$field_aref}=@$value_aref;
                $waived->{$_h{owner}}{$_h{justification}}{$_h{error}}++;
                } while ($value_aref=$sth->fetchrow_arrayref);
            };
        return;
        }; # sub error:

    sub generate_report {
        if (keys %$waived) {
            for my $owner (keys %$waived) {
                for my $justification (keys %{$waived->{$owner}}) {
                    say sprintf("WAIVED (%d waiver, 0 errors) - %s",scalar keys %{$waived->{$owner}{$justification}},join ',',@+{qw(stage process block)});
                    say sprintf("    Error: %s",$_)
                        for (keys %{$waived->{$owner}{$justification}});
                    say sprintf("    Waiver Owner: %s\n    Justification: %s\n",$owner,$justification);
                    };
                };
            };
        if (keys %$failed) {
            say sprintf("FAILED (No waiver, %d errors) - %s",scalar keys %$failed,join ',',@+{qw(stage process block)});
            say sprintf("    Error: %s",$_)
                for (keys %$failed);
            say '';
            };
        }; # sub generate_report:

# Create our regexp --- we will doing the heavy lifting here
my $regex=qr{
    (^Stage:\ (?<stage>\w+)\ *$)            (?{ stage })     # recognize beginning of a segment
    \s
    (^Process:\ (?<process>\w+)\ *$)        (?{})
    \s
    (^Block:\ (?<block>\w+)\ *$)            (?{})
    \s+
    (
        (^Error:\ (?<error>[-\ ()\w]+)\ *$) (?{ error }) # Sending error and its context to (the sub) error
        \s
    )+                                      (?{ generate_report })
    }mnxx;

# Read the test data
my $test=do {
    local $/;
    open my $data,'<','text.txt'
        or die "Could NOT open 'text.txt'! $!";
    <$data>;
    };

my $chaff;
while ($test =~ m{\G(?:$regex|(?<chaff>.*(?=^Stage:)))}gms) {
    # We have completely processed a "segment" and generated a report
    # Stash the $POSTMATCH in case there are no further matches
    $chaff=$POSTMATCH;
    # Handle any "chaff" between parsable segments
    warn "Failed to parse:\n".Data::Dumper->new([\"$+{chaff}"],[qw(*chaff)])->Deepcopy(1)->Indent(1)->Maxdepth(3)->Sortkeys(1)->Dump(),q{ }
        if (defined $+{chaff} && $+{chaff} !~ m{^\s*$});
    # Now we are ready to try for the next segment
    };
warn "Failed to parse:\n".Data::Dumper->new([\$chaff],[qw(*chaff)])->Deepcopy(1)->Indent(1)->Maxdepth(3)->Sortkeys(1)->Dump(),q{ }
    unless ($chaff =~ m{^\s*$});
__DATA__

字符串
我修改了您的输入数据,以便在有效段之间包含一些虚假信息,这就是为什么您会发现“解析失败”消息的原因。修改后的输入对应的输出如下所示:

WAIVED (3 waiver, 0 errors) - stage1,process1,block1
    Error: Port 1 does not exist
    Error: Port 0 does not exist
    Error: Port a0 does not exist
    Waiver Owner: Alex
    Justification: testing

WAIVED (1 waiver, 0 errors) - stage1,process1,block1
    Error: Port 0 does not exist
    Waiver Owner: Eve
    Justification: testing

FAILED (No waiver, 4 errors) - stage1,process1,block1
    Error: Port b3 does not exist
    Error: Port c5 does not exist
    Error: Nothing matched for port_list (SEL-005)
    Error: Port a1 does not exist

Failed to parse:
$chaff = \'
some junk

';
  at try.t line 117.
WAIVED (3 waiver, 0 errors) - stage1,process1,block1
    Error: Port a0 does not exist
    Error: Port 0 does not exist
    Error: Port 1 does not exist
    Waiver Owner: Alex
    Justification: testing

WAIVED (1 waiver, 0 errors) - stage1,process1,block1
    Error: Port 0 does not exist
    Waiver Owner: Eve
    Justification: testing

FAILED (No waiver, 4 errors) - stage1,process1,block1
    Error: Port c5 does not exist
    Error: Port a1 does not exist
    Error: Nothing matched for port_list (SEL-005)
    Error: Port b3 does not exist

Failed to parse:
$chaff = \'

More trash';
  at try.t line 120.


再次感谢!

相关问题