繁体   English   中英

Perl - 比较两个大的 txt 文件并从第一个返回所需的行

[英]Perl - Compare two large txt files and return the required lines from the first

所以我对 perl 编程很陌生。 我有两个 txt 文件,combined_gff.txt 和 pegs.txt。 我想检查 pegs.txt 的每一行是否是针对 combined_gff.txt 和 output 中的任何行的 substring 仅来自名为 Z78E6221F6393D1356Z881DBCE63 的单独文本文件中的 combine_gff.txt 中的那些行

但是我的代码返回空。 请问有什么帮助吗?

#!/usr/bin/perl -w
use strict;

open (FILE, "<combined_gff.txt") or die "error";
my @gff = <FILE>;
close FILE;

open (DATA, "<pegs.txt") or die "error";
my @ext = <DATA>;
close DATA;

my $str = ''; #final string

foreach my $gffline (@gff) {
    foreach my $extline (@ext) {
        if ( index($gffline, $extline) != -1) {
            
            $str=$str.$gffline;
            $str=$str."\n";
            exit;
        }
    }
}

open (OUT, ">", "output.txt");
print OUT $str;
close (OUT);


第一个问题是退出 如果找到 substring,则永远不会创建 output 文件。

第二个问题是chomp :您不会从行中删除换行符,因此找到 substring 的唯一方法是当来自 pegs.txt 的字符串是来自 combine_gff.txt 的字符串的后缀时。

即使解决了这两个问题,算法也会很慢,因为您将一个文件的每一行与第二个文件的每一行进行比较。 如果它包含几个不同的子字符串,它也会多次打印一行(不确定这是否是你想要的)。

这是一种不同的方法:首先,读取 pegs.txt 中的所有行并将它们组合成一个正则表达式(需要quotemeta以便子字符串中的特殊字符在正则表达式中按字面意思解释)。 然后,逐行读取combined_gff.txt,如果正则表达式匹配该行,则打印它。

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

open my $data, '<', 'pegs.txt' or die $!;
chomp( my @ext = <$data> );
my $regex = join '|', map quotemeta, @ext;

open my $file, '<', 'combined_gff.txt' or die $!;
open my $out,  '>', 'output.txt' or die $!;
while (<$file>) {
    print {$out} $_ if /$regex/;
}
close $out;

我还切换到带有词法文件句柄的open的 3 参数版本,因为它是规范的方式(3 参数版本即使对于名为>filerm *|的文件也是安全的,并且词法文件句柄不是全局的,并且更容易作为 arguments 传递给子例程) . 此外,显示实际错误比仅仅死于“错误”更有帮助。

正如 choroba 所说,您不需要循环内的“退出”,因为它结束了脚本的完整执行,并且您必须向前删除行(LF 您通过 chomp 行执行)以找到匹配项。

按照你脚本的逻辑,我做了一个更正,效果很好。

#!/usr/bin/perl -w
use strict;

open (FILE, "<combined_gff.txt") or die "error";
my @gff = <FILE>;
close FILE;

open (DATA, "<pegs.txt") or die "error";
my @ext = <DATA>;
close DATA;

my $str = ''; #final string

foreach my $gffline (@gff) {
    chomp($gffline);
    foreach my $extline (@ext) {
        chomp($extline);
        print $extline;
        if ( index($gffline, $extline) > -1) {
            
            $str .= $gffline ."\n";
            
            
        }
    }
}

open (OUT, ">", "output.txt");
print OUT $str;
close (OUT);

希望对你有效。

韦尔乔

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM