3

文件.txt

bolt W X Y Z

blake X Y Z

gatlin A B C

powell X Y Z

carl P Q R

格式.txt

blake X Y Z

gatlin B C

carl P Q R

输出.txt

bolt W X Y Z

blake X Y Z

gatlin B C

powell X Y Z

carl P Q R

嘿嗨,我是 perl 新手,我有一个问题。我有 2 个文件,即 FILE.txt 和 FORMAT.txt。我想要 FILE.txt 形式的输出数据,但我想用 FILE.txt 替换数据两个文件共有的 FORMAT.txt 的数据,即与 blake 、 gatlin 和 carl 的行必须在 FILE.txt 中用从 FORMAT.txt 获得的数据替换。所需的输出如 OUTPUT.txt 中所示。我尝试通过查找两个文件之间的差异和共同点来做到这一点。

这是我的代码

my %results = ();  
open FILE1, "< FILE.txt" or die "Could not open file: $! \n"; 
while(my $line = < FILE1>)
{   
$results{$line}=1; 
} 
close(FILE1);  
open FILE2, "<FORMAT.txt" or die "Could not open file: $! \n"; 
while(my $line =< FILE2>) 
{   
$results{$line}++; 
} 
close(FILE2);   
open (OUTFILE1, ">>common.txt") or die "Cannot open $outfile for writing \n"; 
open (OUTFILE, ">>diff.txt") or die "Cannot open $outfile for writing \n";
foreach my $line (keys %results) 
{ 
print OUTFILE $line if $results{$line} == 1;
print OUTFILE1 $line if $results{$line} > 1;

} 
close OUTFILE; 
close OUTFILE1;

从这段代码中,我通过连接两个文件获得输出,即 common.txt 和 diff.txt is FINAL.txt

最终的.txt

bolt W X Y Z

powell X Y Z

gatlin B C

gatlin A B C

blake X Y Z

carl P Q R

但是我期望输出的顺序如 OUTPUT.txt 而不是 FINAL.txt 中所示的任何人都可以帮我解决这个问题吗?

4

3 回答 3

1

你的逻辑有缺陷。:-) 您只是从这两个文件中找到共同和独特的行。有些行对于 FILE.txt 或 FORMAT.txt 可能是唯一的,然后是两个文件共有的行。您说问题是在 FILE.txt 中替换 FORMAT.txt 中与人名匹配的任何值。散列中的项目以随机顺序出现,而不是它们插入散列的顺序。我的想法是将 FORMAT.txt 中的更改值读入哈希,然后打开 FILE.txt 并按原样打印该行或打印 FORMAT.txt 中的替换值。

这也将保留行的顺序(在 FILE.txt 中)。

#!/usr/bin/perl
use strict;
use warnings;
use Inline::Files;

my %format;
while (<FORMAT>) {
    my ($k, $v) = split ' ', $_, 2;
    $format{$k} = $v;
}

while (<FILE>) {
    my ($k, $v) = split ' ', $_, 2;
    print "$k ", $format{$k} || $v;
}

__FILE__
bolt W X Y Z
blake X Y Z
gatlin A B C
powell X Y Z
carl P Q R
__FORMAT__
blake X Y Z
gatlin B C
carl P Q R

输出是:

bolt W X Y Z
blake X Y Z
gatlin B C
powell X Y Z
carl P Q R
于 2012-08-10T02:22:41.267 回答
1

这是一个不使用模块的解决方案。

#!/usr/bin/perl 
use strict; 
use warnings; 

my %data;
my @keys_in_order;

# NOTE: FILE.txt must be processed before FORMAT.txt for the
# logic to be correct, (as below).
for my $file ('FILE.txt', 'FORMAT.txt') {
    open my $fh, "<", $file or die "Unable to open $file for reading. $!";
    while (<$fh>) {
        my ($k, $v) = split ' ', $_, 2;
        push @keys_in_order, $k unless grep /$k/, @keys_in_order; 
        push @{ $data{$k} }, $v; 
    }
    close $fh or die "Unable to close $file. $!";
}

for my $key (@keys_in_order) { 
    print "$key $data{$key}->[-1];    } 
于 2012-08-13T01:56:38.780 回答
0

但是如果 FORMAT 中有一个额外的术语,例如“green RS T”,而 FILE 中不存在,如何修改代码

你好云凯莎

抱歉,如果 Inline::Files 让您感到困惑。该模块仅允许您使用这 2 个文件,而无需打开和关闭实际文件。它只是有助于消除打开和关闭代码,以更清楚地公开程序的逻辑。您不会使用它,而是打开 FILE.txt,处理,然后打开 FORMAT.txt 并处理。

我不得不添加一个模块,Tie::IxHash。它用于在将键添加到散列时保留键的顺序(如您所愿)。

克里斯

#!/usr/bin/perl
use strict;
use warnings;
use Tie::IxHash;

# this module will order the keys in the order they were added to the hash
tie my %data, 'Tie::IxHash';

open FILE, "<", 'FILE.txt' or die "Unable to open FILE.txt for reading. $!";
while (<FILE>) {
    my ($k, $v) = split ' ', $_, 2;
    push @{ $data{$k} }, $v;
}
close FILE or die $!;

open FORMAT, "<", "FORMAT.txt" or die "Unable to open FORMAT.txt for reading. $!";
while (<FORMAT>) {
    my ($k, $v) = split ' ', $_, 2;
    push @{ $data{$k} }, $v;
}
close FORMAT or die $!;

for my $key (keys %data) {
    my $aref = $data{$key}; # array reference
    print "$key $aref->[-1]";
}
untie %data;

输出:

bolt W X Y Z
blake X Y Z
gatlin B C
powell X Y Z
carl P Q R
green R S T
于 2012-08-10T14:22:18.103 回答