首页 > 解决方案 > 如何在perl中从另一个文件覆盖一个文件的更改列

问题描述

我有两个文件,如下所示:

文件1:

column1 column2
---------------
h1      0
h2      0
h3      0
h4      0

文件2:

column1 column2
---------------
h1      1
h2      1

我想比较这两个文件并编写一个新文件,如下所示:

column1 column2
---------------
h1      1
h2      1
h3      0
h4      0

最好的方法是什么,因为将文件读取到数组并循环不会完全得到 file3 输出。

标签: perl

解决方案


假设每个文件中每一行的第一个字段是一个“键”,指示是否file1.txt应将 in 的行替换为 in 的行file2.txt,您可以尝试:

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

my %lines;
my @lines;
my $fn = 'file1.txt';
open ( my $fh, '<', $fn ) or die "Could not open file '$fn': $!";
while (my $line = <$fh>) {
    chomp $line;
    my ( $key, @rest ) = split " ", $line;
    push @{ $lines{$key} }, $. ;
    push @lines, $line;
}
close $fh;
my $fn2 = 'file2.txt';
open ( my $fh2, '<', $fn2 ) or die "Could not open file '$fn2': $!";
while( my $line = <$fh2> ) {
    chomp $line;
    my ( $key, @rest ) = split " ", $line;
    if ( exists $lines{$key} ) {
        for my $line_no (@{ $lines{$key} }) {
            $lines[$line_no -1] = $line;
        }
    }
}
close $fh2;

say for @lines;

输出

h1 1
h2 1
h3 0
h4 0

编辑:还将所有未更新的行设置file2.txt为“$ key 0”:

[...]
my %used_keys;
while( my $line = <$fh2> ) {
    chomp $line;
    my ( $key, @rest ) = split " ", $line;
    if ( exists $lines{$key} ) {
        for my $line_no (@{ $lines{$key} }) {
            $lines[$line_no -1] = $line;
        }
        $used_keys{$key} = 1;
    }
}
close $fh2;
delete @lines{ keys %used_keys };
for my $key (keys %lines) {
    for my $line_no (@{ $lines{$key} }) {
        $lines[$line_no -1] = "$key 0";
    }
}
[...]

推荐阅读