[英]Comparing data in two files in Perl
我有两个文件,
文件A:
Folder name A
cp A
cp B
Folder name B
cp D
cp F
文件乙:
Folder name C
cp A
cp B
Folder name A
cp A
cp B
cp C
Folder name B
cp D
cp F
Folder name D
cp A
cp D
输出应该是:
Folder name C:
cp A
cp B
Folder name D
cp A
cp D
Folder name A
cp C
基本上,我想检查文件夹名称是否匹配,然后检查相同文件夹名称的 cp 名称是否匹配。 然后我们需要删除匹配项。 任何人都可以帮助我,因为我是 perl 的新手。
我有代码,它正确地给出了文件夹名称,但删除了一些 cp 名称。
my %file2;
open my $file2, '<', 'fileA.txt' or die "Couldnt open fileA.txt";
while (my $line = <$file2>)
{
++$file2{$line};
}
open my $file1, '<', 'fileB.txt' or die "Couldnt open fileB.txt";
while (my $line = <$file1>)
{
print $fh $line unless $file2{$line};
}
有两个问题:解析您的数据格式,并进行比较。 您不能只是逐行比较文件,您的文件有一个结构,您需要将其解析为 Perl 数据结构。
sub parse_file {
my $file = shift;
open my $fh, '<', $file;
my $in_folder;
my %folders = ();
while(<$fh>) {
# Entering a folder
if( /^Folder name (.*)\s*$/ ) {
$in_folder = $1;
}
# We're in a folder
elsif( $in_folder ) {
# Add a line to the folder actions
if( /^\s+(.*)\s*$/ ) {
push @{$folders{$in_folder}}, $1;
}
# We exited the folder but didn't enter another one
elsif( /^\S/ ) {
$in_folder = '';
}
}
}
return \%folders;
}
这是需要编写和调试的大量额外代码。 如果您的文件存储在诸如 YAML、JSON 或 XML 之类的内容中,您可以使用库来执行此操作。
我故意选择去掉格式并只存储文件夹名称。 这使数据更易于使用,并保护其余代码免受格式更改的影响。
现在每个文件都是文件夹名称的散列,其中包含命令列表。
{
'A' => [
'cp A',
'cp B'
],
'B' => [
'cp D',
'cp F'
]
}
现在我们需要比较它们。 算法是这样的:
幸运的是,我们有Array::Utils来为我们做所有必要的交集和差异。 使用array_diff
查找仅在一个文件中的文件夹,并使用intersection
查找同时存在于两个文件中的文件夹。 然后再次使用array_diff
查找差异。
sub compare_folders {
my($set1, $set2) = @_;
my @set1_names = keys %$set1;
my @set2_names = keys %$set2;
my %diffs;
# It's in one but not the other.
for my $name (array_diff @set1_names, @set2_names) {
$diffs{$name} = $set1->{$name} || $set2->{$name};
}
# It's in both.
for my $name (intersect @set1_names, @set2_names) {
# They're different
if( my @diff = array_diff(@{$set1->{$name}}, @{$set2->{$name}}) ) {
$diffs{$name} = \@diff;
}
}
return \%diffs;
}
最后,我们需要显示结果。 由于我选择使数据通用并去除格式,因此我们需要将其放回原处。
sub display_folder {
my($name, $values) = @_;
my $display = "Folder name $name\n";
for my $value (@$values) {
$display .= " $value\n"
}
return $display;
}
并将它们粘在一起。
my @folders = map { parse_file($_) } @ARGV;
my $diff = compare_folders(@folders);
for my $name (keys %$diff) {
my $values = $diff->{$name};
print display_folder($name, $values);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.