셀과 열의 일치를 기반으로 행렬 테이블 분할

셀과 열의 일치를 기반으로 행렬 테이블 분할

Linux의 파일에 탭으로 구분된 큰 행렬이 있습니다.

Name    ID  ABC12   ABCD12  ABCD123 ABCD1234
ABC12   123456  XX  YY  ZZ  JJ
ABC12   123456  XX  YY  ZZ  JJ
ABCD12  123456  XX  YY  ZZ  JJ
ABCD12  123456  XX  YY  ZZ  JJ
ABCD123 123456  XX  YY  ZZ  JJ
ABCD123 123456  XX  YY  ZZ  JJ
ABCD1234    123456  XX  YY  ZZ  JJ
ABCD1234    123456  XX  YY  ZZ  JJ

이 행렬을 첫 번째 열의 일치 항목을 기반으로 별도의 파일로 분할하고 싶습니다. [이 파일은 용량이 커서 열 수를 셀 수 없습니다.]

예상 출력:

파일 1;

Name    ID  ABC12
ABC12   123456  XX
ABC12   123456  XX

파일 2;

Name    ID  ABCD12
ABCD12  123456  YY
ABCD12  123456  YY

파일 3;

Name    ID  ABCD123
ABCD123 123456  ZZ
ABCD123 123456  ZZ

파일 4;

Name    ID  ABCD1234
ABCD1234    123456  JJ
ABCD1234    123456  JJ

답변1

충분히해결책:

awk 'NR==1{ len=split($0,a_pos); for(i=1;i<=len;i++) a_keys[a_pos[i]]=i }
     NR>1{ if(!r[$1]++) { fn="file"++c; print "Name\tID\t"$1 > fn } 
           print $1,$2,$(a_keys[$1]) > fn 
     }' OFS='\t' file
  • len=split($0,a_pos)- 첫 번째 행을 "키" 배열( a_pos정수로 인덱스된 배열) 로 분할합니다.

  • for(i=1;i<=len;i++) a_keys[a_pos[i]]=i- 문자열 키로 인덱싱할 배열로 뒤집기 a_pos(추가 처리를 위해)a_keys

  • fn="file"++c- 구성 파일 이름


결과 보기:

for f in file[0-9]*; do (echo "$f"; cat "$f"; echo); done

출력( file1, file2및 연속 file3file4):

file1
Name    ID  ABC12
ABC12   123456  XX
ABC12   123456  XX

file2
Name    ID  ABCD12
ABCD12  123456  YY
ABCD12  123456  YY

file3
Name    ID  ABCD123
ABCD123 123456  ZZ
ABCD123 123456  ZZ

file4
Name    ID  ABCD1234
ABCD1234    123456  JJ
ABCD1234    123456  JJ

답변2

당신이 사용할 수있는 awk:

awk 'NR>1{if ($1!=p){N="file"++C; print "Name\tID\t"$1 >N};
             print $1,$2,$(C+2)>N}{p=$1}' infile.txt

답변3

제가 생각할 수 있는 가장 간단한 방법은 첫 번째 줄을 변수로 저장하고 나머지는 필요에 따라 인쇄하는 것입니다. 그러나 이를 위해서는 전체 입력 파일을 메모리에 저장해야 합니다.

#!/bin/gawk -f
{
    if(NR==1){
        header[1]=$1;
        header[2]=$2;
        for(i=3;i<=NF;i++){
            header[$i]=i;
        }
    }
    else{
        data[$1][NR]=$2"\t"$(header[$1]);
    }
}
END{
    OFS="\t";
    for(i in data){
        print header[1],header[2],i > i".txt"
        for(k in data[i]){
            print i,data[i][k] >> i".txt"
        }
    }
}

스크립트를 foo.awk실행 파일( chmod a+x foo.awk)로 저장하고 파일에서 실행합니다.

foo.awk file

답변4

용법: ./split_matrix.awk input.txt

#!/usr/bin/awk -f

BEGIN {
    cnt = 1;
}

NR == 1 { 
    for(i = 3; i <= NF; i++) {
        headers[$i] = i;            
    }   
}
NR > 1 { 
    if( ! file_names[$1]) {
        file_names[$1] = cnt++;
        printf "%s %s %s\n", "Name", "ID", $1 > "file_"file_names[$1];
    }   
    printf "%s %s %s\n", $1, $2, $headers[$1] >> "file_"file_names[$1];
}

시험

입력하다

Name    ID  ABC12   ABCD12  ABCD123 ABCD1234
ABC12   123456  XX  YY  ZZ  JJ
ABC12   123456  XX  YY  ZZ  JJ
ABCD12  123456  XX  YY  ZZ  JJ
ABCD12  123456  XX  YY  ZZ  JJ
ABCD123 123456  XX  YY  ZZ  JJ
ABCD123 123456  XX  YY  ZZ  JJ
ABCD1234    123456  XX  YY  ZZ  JJ
ABCD1234    123456  XX  YY  ZZ  JJ

산출( tail -n +1 -- file*파일 이름과 파일 내용을 인쇄하기 위해 이 트릭을 찾았습니다.여기)

==> file_1 <==
Name ID ABC12
ABC12 123456 XX
ABC12 123456 XX

==> file_2 <==
Name ID ABCD12
ABCD12 123456 YY
ABCD12 123456 YY

==> file_3 <==
Name ID ABCD123
ABCD123 123456 ZZ
ABCD123 123456 ZZ

==> file_4 <==
Name ID ABCD1234
ABCD1234 123456 JJ
ABCD1234 123456 JJ

관련 정보