比较 csv 文件中的值 [英] Compare values in csv files

查看:22
本文介绍了比较 csv 文件中的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在比较两个 csv 文件中的不同值.如果我没有匹配,我想在我的管理系统中添加(或更新)我的设备.

output1.csv (name, ip) - 主系统

<小时>

 Test1, 10.56.7.13测试2,10.56.4.14测试3,10.56.5.15

output2.csv (id,name,ip) - 辅助系统

<小时>

 1234,Test1, 10.56.7.131235,测试2,10.56.4.10

我的结果应该是:我对 Test1 什么都不做(因为它已经在 System 2 中),我应该更新 Test2 (因为现在我有一个不同的 IP 地址) 我应该添加 Test3,因为我在辅助系统中没有它.

使用严格;使用警告;使用特征 qw(say);使用自动模;使用常量 {文件_1 =>"输出 1.csv",文件_2 =>"output2.csv",};我的第一次;我的 $name_first;我的 $ip_first;打开我的 $output_1, "<", FILE_1;而(<$output_1>){咀嚼;($name_first, $ip_first) = 拆分/,/;#/$first{$name_first}=1;$first{$ip_first}=1;}关闭 $output_1;我的%秒;打开我的 $output_2, "<", FILE_2;而(<$output_2>){咀嚼;我的 ($id_second,$name_second,$ip_second) = split/,/;if ( $first{$name_first} && $first{$ip_second} ) {print "找到匹配 $name_second, $ip_second
";if ( $first{$name_first} eq $first{$name_second} &&$first{$ip_first} 和 $first{$ip_second}){print "应该更新 $name_second
";别的print "应添加设备:$name_first
"$秒{$name_second}++;}}}关闭 $output_2;

我在这一行 if ($first{$name_first} eg $first{$name_second} 遇到错误.我认为我的比较是错误的 - 有没有更好的方法?

还有一个问题:对于 UPDATE(PUT 请求),我需要单独的键.因为我在 URL 中需要我的 id 并且我需要放入 XML 模板 nameipaddress,应该添加.我可以这样做吗?

其他{说需要为 $second{$name} 进行更新";我的 $xml = XML::Twig ->新的->解析文件('template.xml');$xml ->set_pretty_print('indented_a');打开(我的 $input, '<', 'output2.csv')或死 $!;而(<$输入>){咀嚼;我的 $id, 我的 $name, $second{$name} = split/,/;$xml ->根->set_att('name', $name );$xml ->get_xpath('//ipaddress',0) ->set_text($second{$name});我的 $uri="https://hostname:9060/ers/config/networkdevice/$id";

解决方案

对于所描述的任务,您需要将第二个文件的每一行与第一个文件中的所有 name-ip 进行比较,从而与它的所有行进行比较.一种有效的方法是首先为每个文件构建哈希.

请注意,最好使用 CSV 模块,例如 Text::CSV,比手工做;否则有很大的麻烦.例如,请参阅这篇文章中的答案.我将您的方法保留在下面,以便专注于实际处理.

使用严格;使用警告;使用特征 qw(say);我的 ($file_1, $file_2) = ('output1.csv', 'output2.csv');open my $fh, '<', $file_1 or die "Can't open $file_1: $!";我的 %first = map { chomp;拆分/s*,s*/} <$fh>;#/open $fh, '<', $file_2 or die "Can't open $file_2: $!";我的 %second = map { chomp;(拆分/s*,s*/)[1,2] } <$fh>;关闭 $fh;foreach 我的 $name(排序键 %first){如果(不存在 $second{$name}){说应该添加设备:$name";下一个;}if ($first{$name} eq $second{$name}) {说找到匹配$name,$first{$name}";}别的 {说需要为 $second{$name} 完成更新"}}

打印出来

<上一页>找到匹配 Test1, 10.56.7.13需要对 10.56.4.10 进行更新应添加设备:Test3

评论

  • 我已将文件命名更改为词法变量,因为我没有看到为此使用 constant 的意义

  • 我使用一个文件句柄,重新打开时会关闭(对于第二个文件)

  • 当每一行被split 时返回的对直接分配散列.如果您需要更多处理(可能是第二个文件的id")或检查对显式循环的输入更改.以这种方式分配哈希还假定名称是唯一的(名称只出现在一行上).

  • 这假设文件不是很大,因为它们都是先读取的

问题中的代码完全损坏,存在基本语法错误.在断定它失败之前总是清理你的代码.如果这是发帖的问题尽你所能.

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
";
        if ( $first{$name_first} eq $first{$name_second} &&  
            $first{$ip_first} ne $first{$ip_second}) 
        {   
            print "It should be done UPDATE for $name_second
";
            else
            print "Devices should be added: $name_first
"
            $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";

解决方案

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.

这篇关于比较 csv 文件中的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆