1

perl を使用して一致する行を抽出することは私にはわかっていますが、一致しない 2 つのファイルから行が必要です。つまり、2 つのテキスト ファイルの中でファイルに固有のものです。

ファイル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行

ファイル 2 :

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のデータを提供します。

4

4 に答える 4

2

最初にファイルの1つを読み込む必要があります。次に、他のファイルの各行の内容と照合できます。私firstList::Utilからそれを行うために使用しました。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は非常に悪いです。どの変数が何をするのか理解するのに苦労しました。

于 2012-11-21T08:45:48.963 に答える
2

コードを改善するのに役立つだけです:

foreach(@2) {
    @org=split('\t',$_);
    chomp($two=$_);
    foreach(@1) {
        if($_=~m/^$two.+/) {
            print OUT1 "$_";
        } else {
            print OUT2 "$_";
        }
    }
}

内側のループのコードが実行される頻度を知っていますか? scalar(@2) * scalar(@1)あなたの例では約400万回です。これが、ファイルが大きくなる理由です。内側のループを次のように置き換えます

$matched=0;
foreach(@1) {
    if($_=~m/^$two.+/) {
        $matched=1;
        last;
    }
}
if($matched) {
    print OUT1 $_;
} else {
    print OUT2 $_;
}

内側のループは一致を追跡し、ファイルへの書き込みは外側のループでのみ行われるようになりました。私はあなたのコーディングスタイルに適応しようとしたことに注意してください!

コーディングスタイル!ぐっ!:D

そのコーディング スタイルは、過去 1000 年間のものです。コードをより安全に、より読みやすく、よりデバッグしやすくする方法について、いくつかのメモを追加させてください。

  • 常にuse strict;およびuse warnings;。そうすれば、多くのエラーを早期に見つけることができます。
  • グローバル(パッケージ)変数を使用しないでください。これは、strictures を誘惑するものではありません。レキシカル変数 ( my @lines = ...) を使用します。
  • 適切な変数名を使用してください:@1あまり役に立ちません。実際、その単一の要素 ( ) を使用すると、Perl の正規表現キャプチャ変数である$1[42]ため、非常に紛らわしく見えます。$1とても詩的である必要はありません。シンプル@linesに動作しますが、@gargravarrよりも優れてい@1ます。
  • 必要がない場合は、文字列補間を使用しないでください。許容される用途: "Hi $name, what's up?". 悪い: print "$_". を使用するだけprint $_です。
  • 空白を使用します。if($_=~m/^$two.+/)ラインノイズのようです。比較のために、手作りの壮大な美しい Perl コードを見てください。
foreach my $line (@lines) {
    $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 $_;
}

今はとても気分が良くなりました!:)あなたが何をしているかを知ってください!コード スニペットをコピー アンド ペーストしないでください。

于 2012-11-21T10:41:31.090 に答える
0

私はこれを得た; ただし、比較するデータは両方のファイルで 1 列にする必要があります。

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";
}
于 2012-11-26T06:39:07.257 に答える
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 はファイルです。

于 2012-11-21T09:01:52.997 に答える