AWK - 열에 관한 질문

AWK - 열에 관한 질문

질문이 있습니다. 나는 이것을 스스로 알아 내려고 노력했지만 awk그것을 작동시키기에 는 너무 새로운 것 같습니다 .

파일(예: Database.txt)이 있다고 가정합니다(값은 탭으로 구분됨).

NA64715 YU24921 MI84612 MI98142 NA94732    
3241531 4957192 4912030 6574918 0473625     
0294637 9301032 8561730 8175919 8175920     
9481732 9359032 8571930 8134983 9385130     
9345091 9385112 2845830 4901742 3455141     

별도의 파일(예 populations.txt: )에는 어떤 ID가 어떤 그룹에 속하는지에 대한 정보가 있습니다. 예를 들면 다음과 같습니다.

NA64715 Europe    
YU24921 Europe    
MI84612 Asia    
MI98142 Africa    
NA94732 Asia    

내가 해야 할 일은 awk모든 그룹(유럽, 아시아, 아프리카)에 대한 열이 포함된 별도의 파일을 강제로 생성하는 것입니다. 처리해야 할 파일이 크기 때문에 단순히 열 수를 세고 번호를 매기고 간단한 방법으로 처리할 수 없습니다. 어떤 ID가 어떤 인구(유럽인 등)에 속하는지 확인한 awk다음 데이터베이스 파일에서 특정 열을 찾은 다음 전체 열을 새 파일(모든 인구에 대해 별도)에 복사해야 합니다.

결과는 다음과 같아야 합니다.

파일 1( europe.txt):

NA64715 YU24921     
3241531 4957192     
0294637 9301032     
9481732 9359032    
9345091 9385112      

파일 2( asia.txt)

MI84612 NA94732    
4912030 0473625    
8561730 8175920    
8571930 9385130    
2845830 3455141    

파일 3( africa.txt)

MI98142     
6574918    
8175919    
8134983    
4901742    

누구든지 이 문제를 해결하도록 도와줄 수 있나요?

답변1

이는 파일을 한 번에 탐색하며 전체 파일을 메모리에 저장할 필요가 없습니다. 각 대상 파일에 대해 열린 파일 설명자를 유지합니다.

awk -F '\t' '
    NR==FNR {population[$1]=$2; next}
    FNR==1 {
        for (i=1; i<=NF; i++) {
            destination[i] = population[$i] ".txt"
        }
    }
    {
        delete separator
        for (i=1; i<=NF; i++) {
            printf "%s%s", separator[destination[i]], $i > destination[i]
            separator[destination[i]] = FS
        }
        for (file in separator) {
            printf "\n" > file
        }
    }
' populations.txt database.txt

답변2

나는 이것이 최선의 접근 방식이 아니라고 생각합니다. 왜냐하면 우리가 가지고 있는 지역에 1을 더한 만큼 여러 번 Database.txt를 읽어야 하기 때문입니다. 아쉽게도 다른 방법은 생각나지 않았습니다.

  1. Database.txt를 바꿉니다:

    awk '{for(i=1;i<=NF;i++){a[NR,i]=$i}}NF>p{p=NF}END{for(j=1;j<=p;j++ ){str=a[1,j];for(i=2;i<=NR;i++){str=str" "a[i,j];}print str}}' 데이터베이스.txt > 데이터베이스.tmp

더 읽기 쉽습니다(동일한 명령):

awk '
{ 
    for (i=1; i<=NF; i++)  {
        a[NR,i] = $i
    }
}
NF>p { p = NF }
END {    
    for(j=1; j<=p; j++) {
        str=a[1,j]
        for(i=2; i<=NR; i++){
            str=str" "a[i,j];
        }
        print str
    }
}' database.txt > database.tmp

2. ids가 포함된 파일을 읽고 전치된 Database.tmp에서 모든 ID를 grep합니다.

while read id region ; do grep -m 1 $id database.tmp >> $region.txt.tmp ; done < population.txt

3. 모든 Region.txt.tmp 파일을 필요한 형식으로 바꿉니다.

for region_file in *txt.tmp ; do awk '{for(i=1;i<=NF;i++){a[NR,i]=$i}}NF>p{p=NF}END{for(j=1;j<=p;j++){str=a[1,j];for(i=2;i<=NR;i++){str=str" "a[i,j];}print str}}' $region_file > ${region_file%.tmp} ; done

4. 임시 파일 모두 삭제

관련 정보