最後の列は同じですが、他の列は他のファイルの行を比較します。

最後の列は同じですが、他の列は他のファイルの行を比較します。

最後の列が同じである必要があるテキストファイルの連続した行を比較するには?そして、2番目の列の1つ以上の値が一致してはいけません。

  1. 一致するものがある場合は、まずファイルの列6を比較してください。
  2. 次に、列4で一致する行を比較します。列4のすべての値は同じではなく、少なくとも1つの値は異なる必要があります。ここで、HSF1とHIF1ANはライン1、2、3に位置しています。

入力ファイル

chr10   102979  103832  HSF1        305
chr10   102979  103832  HIF1AN  1   305
chr10   102979  103832  HSF1        305
chr10   103124438   103124851   HSF1        471
chr10   103124438   103124851   EGLN1   2   471
chr10   103969896   103970503   HSF1        472
chr10   103969896   103970503   HSF1        472
chr10   39135037    39142175    HSF1        335
chr10   4191461 4191936 HSF1        309
chr10   4191461 4191936 HSF1        309
chr10   42423355    42424014    HSF1        336

結果ファイル

chr10   102979  103832  HSF1        305
chr10   102979  103832  HIF1AN  1   305
chr10   102979  103832  HSF1        305
chr10   103124438   103124851   HSF1        471
chr10   103124438   103124851   EGLN1   2   471

答え1

タブ区切りファイルを想定すると、GNU awkを使用できます。

gawk -F'\t' 'NR == FNR {count[$6][$4]++; next} length(count[$6]) > 1' file file
chr10   102979  103832  HSF1        305
chr10   102979  103832  HIF1AN  1   305
chr10   102979  103832  HSF1        305
chr10   103124438   103124851   HSF1        471
chr10   103124438   103124851   EGLN1   2   471

これはファイルを2回通過します。 1 つ目は、各 $6 に何個の $4 値が発生するかを計算し、2 番目は $6 に複数の $4 値がある場合にレコードを出力します。

単一パスで行うことも可能ですが、複雑さ、メモリ使用量、元の順序が失われる可能性があります。


Perlの同じ論理

perl -Mautodie -e '
    open $f, "<", shift;
    while (<$f>) {
        @F = split /\t/;
        $c{ $F[5] }{ $F[3] }++;
    }
    # re-process the file
    seek $f, 0, 0;
    while (<$f>) {
        @F = split /\t/;
        print if scalar keys %{ $c{$F[5]} } > 1;
    }
' file

答え2

ファイルを1行ずつ読み込み、最後の列の値がバッファ内の他のすべての行と同じ場合はその行をバッファに保存し、それ以外の場合はバッファを処理して空にします。

バッファを処理することは、4番目の列の値を共有しない少なくとも1組の連続行を見つけ、成功した場合にバッファを印刷することを意味します。

より良い出力を取得し、値にアクセスしやすくするために、個々の列とともに正確な行をバッファに格納します。

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

sub process {
    my (@rows) = @_;
    my $different;
    for my $i (1 .. $#rows) {
        $different = 1, last if $rows[ $i - 1 ][4] ne $rows[$i][4];
    }
    print map "$_->[0]\n", @rows if $different;
}

my @buffer;
while (<>) {
    chomp;
    my @columns = split;
    if (! @buffer || $buffer[0][-1] == $columns[-1]) {
        push @buffer, [$_, @columns];
    } else {
        process(@buffer);
        @buffer = [$_, split];
    }
}
process(@buffer);

関連情報