마지막 열은 동일하지만 다른 열은 다른 파일의 행을 비교합니다.

마지막 열은 동일하지만 다른 열은 다른 파일의 행을 비교합니다.

마지막 열이 동일해야 하는 텍스트 파일의 연속된 줄을 비교하는 방법은 무엇입니까? 그리고 두 번째 열의 값 중 하나 이상이 일치하지 않아야 합니다.

  1. 일치하는 항목이 있으면 먼저 파일의 열 6을 비교하세요.
  2. 그런 다음 열 4에서 일치하는 행을 비교합니다. 4열의 모든 값은 동일해서는 안 되며, 적어도 하나의 값은 달라야 합니다. 여기서 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

이는 파일을 두 번 통과합니다. 첫 번째는 각 $6에 대해 몇 개의 $4 값이 발생하는지 계산하고, 두 번째는 해당 $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

파일을 한 줄씩 읽고, 마지막 열의 값이 버퍼의 다른 모든 줄과 동일한 경우 해당 줄을 버퍼에 저장하고, 그렇지 않으면 버퍼를 처리하여 비웁니다.

버퍼를 처리한다는 것은 네 번째 열 값을 공유하지 않는 최소한 한 쌍의 연속 행을 찾고 성공하면 버퍼를 인쇄하는 것을 의미합니다.

더 나은 출력을 얻고 값에 더 쉽게 액세스하기 위해 개별 열과 함께 정확한 행을 버퍼에 저장합니다.

#!/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);

관련 정보