我是Perl的菜鸟,我很难完成这项任务。我有两个单列的CSV文件,我正在尝试将差异打印到第三个文件。
File1:
123
124
125
126
File2:
123
124
127
Expected Output:
125
126
127
这是我到目前为止所做的,但是没有用:
#!/usr/bin/perl
use strict;
use warnings;
my $sheet_1;
my $sheet_2;
my $count1 = 0;
my $count2 = 0;
my $file1 = 'file1.csv';
my $file2 = 'file2.csv';
my $file_out = 'output.csv';
open (FILE1, "<$file1") or die "Couldn't open input file: $!";
open (FILE2, "<$file2") or die "Couldn't open input file: $!";
while( <FILE1> ) {
chomp;
$count1++;
#skip header;
next unless $count1;
my $row_1;
@$row_1 = split( /,/, $_ );
push @$sheet_1, $row_1;
}
@$sheet_1 = sort { $a->[0] <=> $b->[0] } @$sheet_1;
while( <FILE2> ) {
chomp;
$count2++;
#skip header;
next unless $count2;
my $row_2;
@$row_2 = split( /,/, $_ );
push @$sheet_2, $row_2;
}
@$sheet_2 = sort { $a->[0] <=> $b->[0] } @$sheet_2;
OUTER: {
foreach my $row_1 ( @$sheet_1 ) {
foreach my $row_2 ( @$sheet_2 ) {
if (@$row_1[0] eq @$row_2[0]){
last OUTER
}
else{
print "@$row_1[0]\n";
}
}
}
}
close FILE1;
close FILE2;
答案 0 :(得分:1)
您可以使用Text::Diff Perl模块执行此操作。否则,请参阅以下内容:
这是进行比较的一种算法。
use strict;
my @arr1;
my @arr2;
my $a;
open(FIL,"a.txt") or die("$!");
while (<FIL>)
{chomp; $a=$_; $a =~ s/[\t;, ]*//g; push @arr1, $a if ($a ne '');};
close(FIL);
open(FIL,"b.txt") or die("$!");
while (<FIL>)
{chomp; $a=$_; $a =~ s/[\t;, ]*//g; push @arr2, $a if ($a ne '');};
close(FIL);
my %arr1hash;
my %arr2hash;
my @diffarr;
foreach(@arr1) {$arr1hash{$_} = 1; }
foreach(@arr2) {$arr2hash{$_} = 1; }
foreach $a(@arr1)
{
if (not defined($arr2hash{$a}))
{
push @diffarr, $a;
}
}
foreach $a(@arr2)
{
if (not defined($arr1hash{$a}))
{
push @diffarr, $a;
}
}
print "Diff:\n";
foreach $a(@diffarr)
{
print "$a\n";
}
# You can print to a file instead, by: print FIL "$a\n";
答案 1 :(得分:1)
现在提出几个问题:
1, 2, 3
。您将其与其中包含1, 3, 2
的第二个文件进行比较。第二行和第三行有所不同吗?或者,文件是否相同,因为它们包含相同的值?不,如果两个文件在不同的地方都有相同的值,则该值不应该在输出中。在您的示例中,两个文件(1,2,3)和(1,3,2)是相同的。 - Yoboy 7小时前
很好......
每当是第2组类型的第1组中的项目时,您应该考虑哈希。
散列是一个值列表,其中每个值都有一个键。可以是列表中的重复值,但只能是特定键的单个实例。这意味着您可以轻松查看列表中是否已存在密钥。
想象一下,获取文件#1,并将每个值作为密钥放在哈希中。价值观无关紧要,你只关心钥匙。
现在,当您浏览文件#2时,您可以快速查看该密钥是否已存在于您的哈希中。如果是,则为重复值。
我们还可以利用哈希的第二个特性:只允许一个密钥实例。如果我们将两只苍蝇扔进一个哈希怎么办?如果文件#1和文件#2之间的值重复,则无关紧要,该密钥只能有一个实例。
以下是获取两个文件中唯一值列表的方法:
use strict;
use warnings;
use feature qw(say);
use autodie;
use constant {
FILE_1 => "file1.txt",
FILE_2 => "file2.txt",
};
my %hash;
#
# Load the Hash with value from File #1
#
open my $file1_fh, "<", FILE_1;
while ( my $value = <$file1_fh> ) {
chomp $value;
$hash{$value} = 1;
}
close $file1_fh;
#
# Add File #2 to the Hash
#
open my $file2_fh, "<", FILE_2;
while ( my $value = <$file2_fh> ) {
chomp $value;
$hash{$value} = 1; #If that value was in "File #1", it will be "replaced"
}
close $file2_fh;
#
# Now print out everything
#
for my $value ( sort keys %hash ) {
say $value;
}
这将打印出来:
123
124
125
126
127
您想要的是唯一值的列表。这比起初看起来有点棘手。您可以将文件#1的值放入哈希值,然后如果它们不在文件#1中,则打印出文件#2中的值。这将为您提供文件#2中的唯一值列表,但不是文件#1中的唯一值。
因此,您需要创建两个哈希值,一个用于FIle#1,另一个用于文件#2,然后通过每个哈希并将它们相互比较:
use strict;
use warnings;
use feature qw(say);
use autodie;
use constant {
FILE_1 => "file1.txt",
FILE_2 => "file2.txt",
};
#
# Load Hash #1 with value from File #1
#
my %hash1;
open my $file1_fh, "<", FILE_1;
while ( my $value = <$file1_fh> ) {
chomp $value;
$hash1{$value} = 1;
}
close $file1_fh;
#
# Load Hash #2 with value from File #2
#
my %hash2;
open my $file2_fh, "<", FILE_2;
while ( my $value = <$file2_fh> ) {
chomp $value;
$hash2{$value} = 1;
}
close $file2_fh;
现在,我们需要将一个与另一个进行比较。我现在将值存储在数组中:
my @array;
#
# Check if File #1 has unique values vs File #2
#
for my $value ( %keys %hash1 ) {
if ( not exists $hash2{$value} ) {
push @array, $value; #Value in File #1, but not in File #2
}
}
#
# Check if File #2 has unique values vs File #1
#
for my $value ( %keys %hash2 ) {
if ( not exists $hash1{$value} ) {
push @array, $value; #Value in File #2, but not in File #1
}
}
#
# Now print out what's in @array of unique values
#
for my $value ( sort @array ) {
say $value;
}
答案 2 :(得分:0)
即:
use strict;
use warnings;
use 5.012;
use Text::CSV::Slurp;
my $file1_src=<<EOF;
id,field1,field2,field3
123,junk,"quoted junk",junk
124,"quoted junk","quoted junk",junk
125,junk,"quoted junk",junk
126,junk,"quoted junk",junk
EOF
my $file2_src=<<EOF;
id,field1,field2,field3
123,junk,"quoted junk",junk
124,junk,"quoted junk",junk
127,"quoted junk","quoted junk",junk
EOF
my %data1 = map { $_->{id} => 1 } @{Text::CSV::Slurp->load(string => $file1_src)};
my %data2 = map { $_->{id} => 1 } @{Text::CSV::Slurp->load(string => $file2_src)};
for my $id (keys %data1, keys %data2) {
say $id unless $data1{$id} and $data2{$id};
}