3

ファイル.txt

bolt W X Y Z

blake X Y Z

gatlin A B C

powell X Y Z

carl P Q R

FORMAT.txt

blake X Y Z

gatlin B C

carl P Q R

OUTPUT.txt

bolt W X Y Z

blake X Y Z

gatlin B C

powell X Y Z

carl P Q R

こんにちは。perl を初めて使用するので質問があります。FILE.txt と FORMAT.txt という 2 つのファイルがあります。出力データを FILE.txt の形式にしたいのですが、FILE.txt のデータを両方のファイルに共通の FORMAT.txt のデータ、つまり blake 、 gatlin 、および carl の行は、FILE.txt で FORMAT.txt から取得したデータに置き換える必要があります。必要な出力は、OUTPUT.txt に示されているとおりです。2つのファイルの違いと共通点を見つけて、これを試みました。

これは私のコードです

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 という 2 つのファイルを連結して出力​​を得ました。

FINAL.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

しかし、FINAL.txtではなくOUTPUT.txtに示されているように、出力を期待している順序誰でもこれで私を助けてくれますか???

4

3 に答える 3

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 に答える
1

あなたの論理には欠陥があります。:-) 2 つのファイルから共通でユニークな行を見つけているだけです。一部の行は FILE.txt または FORMAT.txt に固有である場合があり、両方のファイルに共通の行があります。問題は、その人の名前に一致する FORMAT.txt の値を FILE.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 に答える
0

しかし、FILE に存在しない "green RS T" のような余分な用語が FORMAT にある場合、コードをどのように変更できますか?

こんにちはウンカイサ

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 に答える