ある列の値を別の列のすべての値と比較する

ある列の値を別の列のすべての値と比較する

2つの入力ファイルがあります。のすべての行をすべてFile1の行と比較する必要がありますFile2

ロジックは次のとおりです。

  1. of が一致しない場合Column1(その下のすべての値)、行全体がFile1出力ファイルに出力されます。同様に、 の各値は の各値と比較されます。Column1File2File1Column1Column1File2

  2. 両方のファイルに一致するエントリがあり、Column1値がその値より大きいか小さい場合は、行全体を印刷して、そのようにすべての行を比較できます。Column2File1N+10N-10NColumn2File2File1File2

File1:

Contig1  23
Contig1  42
Contig2  68
Contig3  89
Contig3  102
Contig7  79

File2:

Contig1  40
Contig1  49
Contig3  90
Contig2  90
Contig20 200
Contig1  24

予想出力:

Contig2  68
Contig3  102
Contig7  79

どんな解決策でも、いawkなくてもsed可能です。

似たような質問を見つけましたが、どうすればいいかわかりません。

コードは次のとおりです。

  `NR==FNR { 
   lines[NR,"col1"] = $1
   lines[NR,"col2"] = $2
   lines[NR,"line"] = $0
   next
    }
   (lines[FNR,"col1"] != $1) {
    print lines[FNR,"line"]
    next
    }
   (lines[FNR,"col2"]+10 < $2 || lines[FNR,"col2"]-10 > $2) {
    print lines[FNR,"line"]
    }' file1 file2`

答え1

以下のスクリプトは次のことを行います。私の考えでは、これがあなたが望むものです。

  1. file1 の contig が file2 にない場合、その contig のすべての行を印刷します。
  2. file2 に存在する場合は、file1 の各値に対して -10 以上、file2 -10 の対応する contig 値より大きい、または file2 +10 の値より大きい場合にのみ印刷します。
#!/usr/bin/env perl

my (%file1, %file2);

## read file1, the 1st argument
open(F1,"$ARGV[0]");
while(<F1>){
    chomp;
    ## Split the line on whitespace into the @F array.
    my @F=split(/\s+/); 

    ## Save all lines in the %file1 hash.
    ## $F[0] is the contig name and $F[1] the value.
    ## The hash will store a list of all values
    ## associated with this contig.
    push @{$file1{$F[0]}},$F[1];
}
close(F1);
## read file2, the second argument
open(F2,"$ARGV[1]"); 
while(<F2>){
    ## remove newlines
    chomp;
    ## save the fields into array @F
    my @F=split(/\s+/); 
    ## Again, save all values associated with each
    ## contig into the %file2 hash. 
    push @{$file2{$F[0]}},$F[1];
}
close(F2);

## For each of the contigs in file1
foreach my $contig (keys(%file1)) {
    ## If this contig exists in file 2
    if(defined $file2{$contig}){
        ## get the list of values for that contig
        ## in each of the two files
        my @f2_vals=@{$file2{$contig}};
        my @f1_vals=@{$file1{$contig}};
        ## For each of file1's values for this contig
        val1:foreach my $val1 (@f1_vals) {
                ## For each of file2's value for this contig
                foreach my $val2 (@f2_vals) {
                    ## Skip to the next value from file1 unless
                    ## this one falls within the desired range.
                    unless(($val1 < $val2-10) || ($val1 > $val2+10)){
                        next val1;
                    }
                }
                ## We will only get here if none of the values
                ## fell within the desired range. If so, we should
                ## print the value from file1.
                print "$contig $val1\n";
            }
    }
    ## If this contig is not in file2, print the
    ## lines from file1. This will print all lines
    ## from file1 whose contig was not in file2.
    else {
        print "$contig $_\n" for @{$file1{$contig}}
    }
}

テキストファイル(たとえばfoo.pl)に保存して実行可能にした後(chmod a+x foo.pl)、次のように実行します。

./foo.pl file1 file2

あなたの例では、以下を返します。

$ foo.pl file1 file2 
Contig2 68
Contig3 102
Contig7 79

関連情報