Perl - 使用特定子字符串的文件比较

时间:2016-03-03 08:02:14

标签: perl file compare substring

我写了这个脚本来比较两个文件的行,并将公共/非公共行输出到两个不同的文件中。脚本是:

use strict;
use warnings;
use autodie;

my $f1 = shift || "CSP8216.TXT";                                            
my $f2 = shift || "CSP8217.TXT";                                            

open my $fh1, '>', 'file1';
open FH2, '>', 'file2';

my %results;

open my $file1, '<', $f1;                                                   
while (my $line = <$file1>) { 
$results{$line} = 1  
}                           

open my $file2, '<', $f2;                                                   
while (my $line = <$file2>) {
   $results{$line}++ 
}                           

foreach my $line (sort { $results{$b} <=> $results{$a} } keys %results) 
{   
    if ($results{$line} >= 1)
    {
    print {$fh1} "$line";
    }
   else 
   {
   print FH2 "$line";
   }
}

我的问题是当我尝试修改此脚本但根据每行的特定子字符串运行比较时,即:

  • 如果文件A的一行的特定子字符串与文件B中某行的另一个特定子字符串匹配,则将文件B的所述/整行/行输出到fh1,否则将其输出到fh2。

我试过这个,但它不起作用 - 对Perl来说真的很新,任何帮助都会非常感激:

use strict;
use warnings;
use autodie;

my $f1 = shift || "CSP8216.TXT";                                            
my $f2 = shift || "CSP8216.TXT";                                            

open my $fh1, '>', 'file1';
open FH2, '>', 'file2';

my %results;

open my $file1, '<', $f1;                                                   
while (my $line = <$file1>) 
{
    my $sbs1 = substr($line, 0, 10); 
    $results{$sbs1} = 1 
}                           

open my $file2, '<', $f2;                                                   
while (my $line = <$file2>) 
{
    my $sbs2 = substr($line, 0, 10);
    $results{$sbs2}++ 
}                           

foreach my $line (sort { $results{$b} <=> $results{$a} } keys %results) 
{   
    if ($results{$line} >= 1)
    {
    print {$fh1} "$line";
    }
    else 
    {
    print FH2 "$line";
    }
}

这不起作用,我感觉它在逻辑上有问题,它只输出一行中的子串。

2 个答案:

答案 0 :(得分:2)

根据我的评论,如果我们需要支持单行在一个文件中出现两次,我们需要将文件A和文件B中的行分开。

On选项是解决像这样的基本问题

open my $fh1, '<', $filename1 or die "Can't open $file1: $!";
while (my $line = <$fh1>) {
    $combined{$line} = $file1{$line} = 1;
}

open my $fh2, '<', $filename2 or die "Can't open $file2: $!";
while (my $line = <$fh2>) {
    $combined{$line} = $file2{$line} = 1;
}

open my $out1, '>', $outfilename1 or die "...";
open my $out2, '>', $outfilename2 or die "...";

for my $line (keys %combined) {
    if ($file1{$line} && $file2{$line}) {
        print $out1 $line;
    } else {
        print $out2 $line;
    }
}

要解决子字符串问题,我会将每个文件的子字符串保留为哈希中的键。但是,不是仅存储真值,而是将完整字符串存储为%file2中的值:

open my $fh1, '<', $filename1 or die "Can't open $file1: $!";
while (my $line = <$fh1>) {
    my $substr = substr($line, 0, 10);
    $combined{$line} = $file1{$substr} = 1;
}

open my $fh2, '<', $filename2 or die "Can't open $file2: $!";
while (my $line = <$fh2>) {
    my $substr = substr($line, 20, 30);
    $combined{$line} = 1;
    $file2{$substr} = $line;
}

open my $out1, '>', $outfilename1 or die "...";
open my $out2, '>', $outfilename2 or die "...";

for my $line (keys %combined) {
    my $substr1 = substr($line, 0, 10);
    my $substr2 = substr($line, 20, 30);
    if ($file1{$substr1} && $file2{$substr2}) {
        print $out1 $file2{$substr2};
    } else {
        print $out2 $line;
    }
}

答案 1 :(得分:0)

这对我有用

#!/usr/bin/perl

use warnings;
use autodie;

my %results;

my $f1 = shift || "CSP8216.TXT";
my $f2 = shift || "CSP8217.TXT";

open my $fh1, '>', 'file1';
open my $fh2, '>', 'file2';


open my $file1, '<', $f1;
while (my $line = <$file1>) {
    my $sbs1 = substr($line, 0, 10);
    $results{$sbs1} = 1
}

open my $file2, '<', $f2;
while (my $line = <$file2>) {
    my $sbs2 = substr($line, 0, 10);
    if (!$results{$sbs2}) {
        $results{$sbs2} = 1;
    }
    $results{$sbs2}++
}

foreach my $line (sort { $results{$b} <=> $results{$a} } keys %results) {
    if ($results{$line} > 1) {
        print {$fh1} "$line";
    }
    else {
        print {$fh2} "$line";
    }
}