我知道使用perl提取匹配行但我想要两个不匹配的文件中的行,即它们对于两个文本文件中的文件是唯一的。
文件1 :
one|E2027.1|073467|66 ATGCTATGTTTTGCTAAT
one|E2002.1|073405|649 ATGAAAGCTTTAAAGAAA
one|E2001.1|734704|201 ATGTTTTCAGGTATTATA
one|E2025.1|073468|204 ATGAAACAGAAATATATT
one|E2028.1|073431|578 ATGTTATTTAATTATGGT
one|E2040.1|073743|862 ATGATTTATCCTAATAAT
.........〜2000这样的行
file2 :
one|E2027.1|073467|66
one|E5005.5|000005|005
one|E2001.1|734704|201
one|E2025.1|073468|204
one|E2028.1|073431|578
one|E2040.1|073743|862
.........〜2000这样的行
如何使用perl或cmd命令提取不匹配的行? 这里例如文件2的第2行对于文件2是唯一的..... !!!
这是我到目前为止所拥有的
foreach(@2) {
@org=split('\t',$_);
chomp($two=$_);
foreach(@1) {
if($_=~m/^$two.+/) {
print OUT1 "$_";
} else {
print OUT2 "$_";
}
}
}
但是输出提供GB数据。
答案 0 :(得分:2)
您必须首先阅读其中一个文件。然后,您可以匹配其他文件的每一行的内容。我使用了来自List::Util的first
来做到这一点。 grep
也很好,但是first
在找到第一次出现后停止,这样可以节省大文件的时间。
use strict;
use warnings;
use List::Util qw(first);
use 5.014;
my $file1 = <<"FILE1";
one|E2027.1|073467|66\tATGCTATGTTTTGCTAAT
one|E2002.1|073405|649\tATGAAAGCTTTAAAGAAA
one|E2001.1|734704|201\tATGTTTTCAGGTATTATA
one|E2025.1|073468|204\tATGAAACAGAAATATATT
one|E2028.1|073431|578\tATGTTATTTAATTATGGT
one|E2040.1|073743|862\tATGATTTATCCTAATAAT
FILE1
my $file2 = <<"FILE2";
one|E2027.1|073467|66
one|E5005.5|000005|005
one|E2001.1|734704|201
one|E2025.1|073468|204
one|E2028.1|073431|578
one|E2040.1|073743|862
FILE2
my @file1_content = map { (split(/\t/))[0] } split /\n/, $file1;
foreach my $line (split /\n/, $file2) {
chomp $line; # we need that because the split above is just a filler
next if first { $_ eq $line } @file1_content;
say $line;
}
我强烈建议您在所有程序中使用strict
和warnings
。他们都帮助你找到小的,微妙的错误。以更具描述性的方式命名变量也是一个好主意。名为@1
和@2
的数组非常糟糕。我无法理解哪个变量做了什么。
答案 1 :(得分:2)
只是为了帮助您改进代码:
foreach(@2) {
@org=split('\t',$_);
chomp($two=$_);
foreach(@1) {
if($_=~m/^$two.+/) {
print OUT1 "$_";
} else {
print OUT2 "$_";
}
}
}
你知道内循环代码执行的频率吗? scalar(@2) * scalar(@1)
次,在你的例子中约为4百万。这就是为什么你的文件变得那么大的原因。用
$matched=0;
foreach(@1) {
if($_=~m/^$two.+/) {
$matched=1;
last;
}
}
if($matched) {
print OUT1 $_;
} else {
print OUT2 $_;
}
内部循环现在跟踪匹配并且只在外部循环中写入文件。 请注意,我尝试适应您的编码风格!
编码风格从上一个千年开始!让我添加一些注释,让您的代码更安全,更可读,更可调试:
use strict;
和use warnings;
。很多错误都可以尽早找到。strict
ures的。使用词汇变量(my @lines = ...
)。@1
不是很有用。实际上,使用其单个元素($1[42]
)看起来非常混乱,因为$1
是Perl的正则表达式捕获变量。它不一定非常富有诗意。一个简单的@lines
可以使用,但即使@gargravarr
也优于@1
。"Hi $name, what's up?"
。不好:print "$_"
。只需使用print $_
。if($_=~m/^$two.+/)
看起来像线路噪音。为了进行比较,请看看这个手工制作的美丽Perl代码片段:foreach my $line (@lines) { print $differences $line if $line =~ /^$prefix.*/; }
因此,让我们尝试重写该代码:
my $matched = 0;
foreach my $line (@lines) {
if ($line = ~/^$two.+/) {
$matched=1;
last;
}
}
if ($matched) {
print OUT1 $_;
} else {
print OUT2 $_;
}
现在感觉好多了! :) 知道你在做什么!不要只是复制'n'拼贴代码片段。
答案 2 :(得分:0)
#!/usr/bin/perl
use strict;
use warnings;
open my $fh1 ,'<', 'f1' or die $!;
open my $fh2 ,'<', 'f2' or die $!;
chomp(my @ar1=<$fh1>);
chomp(my @ar2=<$fh2>);
close $fh1;
close $fh2;
my @ar3=();
foreach my $x (@ar2) {
push @ar3, $x if not grep (/^\Q$x\E/,@ar1);
}
print "@ar3";
其中f1和f2是你的文件。
答案 3 :(得分:0)
我得到了这个;如果要比较的数据应该在两个文件中都是单列
use strict;use warnings;
print "Enter file1: ";
chomp($file=<STDIN>);
open(FH,$file);
print"Enter file2: ";
$hspfile=<STDIN>;
open(FH1,$hspfile);
my $list1;
my $list2;
my @list1 =<FH1> ;my @list2 =<FH> ;
print "enter output file1 : ";
$out = <STDIN>;
chomp($out);
open(OUT,">$out");
LIST2: foreach $list2 (@list2){
LIST1: foreach $list1 (@list1){
if ("$list2" eq "$list1") {
next LIST2;
}
}
print OUT"$list2";
}