如何比较两个文本文件并删除匹配的内容并传递给 perl 中的输出



我有两个文本文件 text1.txt 和 text2.txt如下所示

文本1

    ac
    abc
    abcd
    abcde

文本2

    ab
    abc
    acd
    abcd

输出

ac
abcde

我需要比较两个文件,并在第二个文件中有匹配项时从text1中删除内容。

我想要Perl中的代码。目前我正在尝试以下代码。

#!usr/bin/perl
use strict;
use warnings;
open (GEN, "text1.txt") || die ("cannot open general.txt");
open (SEA, "text2.txt") || die ("cannot open search.txt");
open (OUT,">> output.txt") || die ("cannot open intflist.txt");
open (LOG, ">> logfile.txt");
undef $/;
foreach (<GEN>) {
  my $gen = $_;
  chomp ($gen);
  print LOG $gen;
  foreach (<SEA>) {
    my $sea = $_;
    chomp($sea);
    print LOG $sea;
    if($gen ne $sea) {
      print OUT $gen;
    }
  }
}

在此,我从text1获得所有内容,而不是无与伦比的内容。请帮帮我。

我认为您应该读取数组中的 text2,然后在该数组的第二个 foreach 中使用该数组。

@b = <SEA>;

否则在第二个循环中,文件指针已经位于末尾

一种方式:

#!/usr/bin/perl
use strict;
use warnings;
$="n";
open my $fh1, '<', 'file1' or die $!;
open my $fh2, '<', 'file2' or die $!;
open my $out, '>', 'file3' or die $!;
chomp(my @arr1=<$fh1>);
chomp(my @arr2=<$fh2>);
foreach my $x (@arr1){
        print $out $x if (!grep (/^Q$xE$/,@arr2));
}
close $fh1;
close $fh2;
close $out;

执行上述操作后,文件 'file3' 包含:

$ cat file3
ac
abcde
这是我

的计划:

  1. 以哈希形式读取第一个文件的内容,并带有出现次数计数器。例如,使用数据可以获得:

    %lines = ( 'ac' => 1,
        'abc' => 1,
        'abcd' => 1,
        'abcde' => 1);
    
  2. 读取第二个文件,如果键存在,则删除前面的哈希 %lines 。

  3. 将密钥%lines打印到所需的文件。

例:

 use strict;
 open my $fh1, '<', 'text1' or die $!;
 open my $fh2, '<', 'text2' or die $!;
 open my $out, '>', 'output' or die $!;
 my %lines = ();
 while( my $key = <$fh1> ) {
    chomp $key;
    $lines{$key} = 1;
 }
 while( my $key = <$fh2> ) {
    chomp $key;
    delete $lines{$key};
 }
 foreach my $key(keys %lines){
    print $out $key, "n";
 }
 close $fh1;
 close $fh2;
 close $out;

您的主要问题是您未定义输入记录分隔符$/。这意味着整个文件将作为单个字符串读取,您所能做的就是说这两个文件不同。

删除undef $/,事情会好得多。但是,内部for循环将读取并打印file2中与file1的第一行不匹配的所有行。第二次遇到此循环时,已从文件中读取所有数据,因此根本不会执行循环的主体。您必须在外部循环中打开file2,或者将文件读入数组并循环访问该数组。

再说一次,您真的要打印file2中不等于file1中每一行的所有行吗?

更新

正如我在评论中所写,听起来您想输出text1中没有出现在text2任何地方的行.使用哈希可以轻松实现:

use strict;
use warnings;
my %exclude;
open my $fh, '<', 'text2.txt' or die $!;
while (<$fh>) {
  chomp;
  $exclude{$_}++;
}
open $fh, '<', 'text1.txt' or die $!;
while (<$fh>) {
  chomp;
  print "$_n" unless $exclude{$_};
}

使用您在问题中显示的数据,将产生此输出

ac
abcde
我想

这样看待你的问题:

  • 您在 file.txt 中有一组字符串 S
  • 您在 forbidden.txt 中有一组禁止字符串的 F
  • 你想要允许的字符串,所以 S \ F (setminus(。

Perl 中有一个数据结构,它实现了一组字符串:哈希。(它也可以映射到标量,但这在这里是次要的(。

因此,首先我们创建我们拥有的行集。我们让该文件中的所有字符串映射到 undef ,因为我们不需要该值:

open my $FILE, "<", "file.txt" or die "Can't open file.txt: $!";
my %Set = map {$_ => undef} <$FILE>;

我们以相同的方式创建禁止集:

open my $FORBIDDEN, "<", "forbidden.txt" or die "Can't open forbidden.txt: $!";
my %Forbidden = map {$_ => undef} <$FORBIDDEN>;

集合减号的工作方式类似于以下任一方式:

  • 对于 S 中的每个元素 x,x 在结果集中 R iff x 不在 F

    my %Result = map {$_ => $Set{$_}} grep {not exists $Forbidden{$_}} keys %Set;
    
  • 结果集 R 最初为 S。对于 F 中的每个元素,我们从 R 中删除该项:

    my %Result = %Set; # make a copy
    delete $Result{$_} for keys %Forbidden;
    

(keys函数访问字符串集中的元素(

然后我们可以打印出所有密钥:print keys %Result .

但是,如果我们想维护秩序呢?哈希中的条目也可以携带关联的值,那么为什么不能携带行号呢?我们像这样创建集合 S

open my $FILE, "<", "file.txt" or die "Can't open file.txt: $!";
my $line_no = 1;
my %Set = map {$_ => $line_no++} <$FILE>;

现在,这个值与字符串一起携带,我们可以在最后访问它。具体来说,我们将哈希中的键在其行号之后进行排序:

my @sorted_keys = sort { $Result{$a} <=> $Result{$b} } keys %Result;
print @sorted_keys;

注意:所有这些都假定文件由换行符终止。否则,您将不得不chomp.

相关内容

  • 没有找到相关文章

最新更新