Compare values in csv files

2019-03-02 04:18发布

I am comparing different values in two csv files. If I do not have a match, I want to add (or update) my devices in my Management System.

output1.csv (name, ip) - Primary system


 Test1, 10.56.7.13
 Test2, 10.56.4.14
 Test3, 10.56.5.15

output2.csv (id,name,ip) - Secondary system


 1234,Test1, 10.56.7.13
 1235,Test2, 10.56.4.10

My result should be: I do nothing with Test1 (because it is already in System 2), I should update Test2 (because now I have a different ip address) and I should add Test3, because I do not have it in the secondary System.

use strict;
use warnings;
use feature qw(say);
use autodie;

use constant {
    FILE_1  => "output1.csv",
    FILE_2  => "output2.csv",
};

my %first;
my $name_first;
my $ip_first;
open my $output_1, "<", FILE_1;

while ( <$output_1> ) { 
    chomp;
    ($name_first, $ip_first) = split /,/;  #/
    $first{$name_first}=1;
    $first{$ip_first}=1;
}
close $output_1;

my %second;
open my $output_2, "<", FILE_2;

while ( <$output_2> ) { 
    chomp;
    my ($id_second,$name_second,$ip_second) = split /,/;
    if ( $first{$name_first} && $first{$ip_second} ) { 
        print "Match found $name_second, $ip_second\n";
        if ( $first{$name_first} eq $first{$name_second} &&  
            $first{$ip_first} ne $first{$ip_second}) 
        {   
            print "It should be done UPDATE for $name_second\n";
            else
            print "Devices should be added: $name_first\n"
            $second{$name_second}++;
        }   
    }   
}
close $output_2;

I am getting an error at this line if ( $first{$name_first} e.g. $first{$name_second}. I think my compare is wrong - is there a better way of doing it?

One question more: for UPDATE (PUT Request) I need separate keys. Because i need my id in URL and I need to put in XML template name and ipaddress, that should be added. May I do it this way?

else {
    say "UPDATE need be done for $second{$name}";
       my $xml = XML::Twig -> new -> parsefile ( 'template.xml' );
      $xml ->set_pretty_print('indented_a');
   open ( my $input, '<', 'output2.csv' ) or die $!;
      while ( <$input> ) { 
      chomp; 
      my $id, my $name, $second{$name} = split /,/; 
      $xml -> root -> set_att('name', $name ); 
      $xml -> get_xpath('//ipaddress',0) -> set_text($second{$name}); 
      my $uri="https://hostname:9060/ers/config/networkdevice/$id";

1条回答
戒情不戒烟
2楼-- · 2019-03-02 05:08

For the described task you need to compare each line of the second file with all name-ip in the first file, thus with all its lines. An efficient way of doing this is to first build hashes for each file.

Please note that it is much better to use a module for CSV, like Text::CSV, than to do it by hand; there's much chance for trouble otherwise. See answers in this post, for example. I keep your approach below merely so to focus on the actual processing.

use strict;
use warnings;
use feature qw(say);

my ($file_1, $file_2) = ('output1.csv', 'output2.csv');

open my $fh, '<', $file_1  or die "Can't open $file_1: $!";
my %first = map { chomp; split /\s*,\s*/ } <$fh>;            #/

open    $fh, '<', $file_2  or die "Can't open $file_2: $!";
my %second = map { chomp; (split /\s*,\s*/)[1,2] } <$fh>;
close $fh;

foreach my $name (sort keys %first) {
    if (not exists $second{$name}) {
        say "Devices should be added: $name";
        next;
    }

    if ($first{$name} eq $second{$name}) {
        say "Match found $name, $first{$name}";
    }
    else {
        say "UPDATE need be done for $second{$name}"
    }   
}   

This prints

Match found Test1, 10.56.7.13
UPDATE need be done for 10.56.4.10
Devices should be added: Test3

Comments

  • I've changed file naming to lexical variables as I don't see a point in using constant for this

  • I use one filehandle, which gets closed when reopened (for the second file)

  • A hash is assigned directly by pairs returned when each line is split. If you need more processing (perhaps 'id' for the second file) or checking of input change to an explicit loop. Assigning a hash this way also assumes unique names (names appear on only one line).

  • This assumes that files aren't huge as they are both read first

The code in the question is completely broken, with basic syntax errors. Always clean up your code before concluding that it fails. If this is a matter of posting please do your best with what you post.

查看更多
登录 后发表回答