다른 파일 범위 내에서 한 파일의 값을 찾아 상위 값을 선택합니다.

다른 파일 범위 내에서 한 파일의 값을 찾아 상위 값을 선택합니다.

A, B 두 개의 파일이 있습니다. 파일 A에는 4개의 열과 600,000개의 행이 있습니다. 파일 B에는 4개의 열과 5000개의 행이 있습니다. 예:

파일-A:

ENSB1 1 12245 0.53 0.002
ENSB2 1 13400 0.27 0.0003
ENSB3 1 14780 0.13 0.00001
ENSB4 1 15201 0.33 0.9
ENSB5 2 56259 0.70 0.0002
ENSB6 2 57000 0.42 0.00004
ENSB7 2 58200 0.50 0.5

파일-B:

1 12000 15000 G1
1 14000 16000 G2
2 56000 59000 G3

File-B의 첫 번째 줄을 선택하고 싶습니다. 그런 다음 파일 A의 열 3에 있는 값이 파일 B의 열 2와 3에 있는 값의 범위 내에 속하도록 파일 A의 여러 행을 식별하려고 합니다. 파일 A의 2열도 파일 B의 2열과 3열의 값 범위에 속하며, 파일 B의 1열의 값은 일치합니다. File-A의 여러 행이 위 조건을 충족할 것으로 예상합니다. 위 기준에 따라 여러 행이 식별되면 파일 A의 해당 행 중 5열의 가장 낮은 값이 선택되어 파일 B의 해당 행에 있는 새 열에 기록됩니다. File-B의 모든 줄에 대해 이 단계를 반복합니다.

예상되는 새 파일:

1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004

저는 Linux 명령을 처음 배우는 사람인데 누구든지 도움을 주시면 좋을 것 같습니다.

답변1

노력하다

awk 'NR==FNR   {Line[FNR] = $0           # first file processing
                Cat[FNR]  = $1
                Min[FNR]  = $2
                Max[FNR]  = $3
                Low[FNR]  = 1E10         # initialize to high number so first value from file2 will be lower
                ML        = FNR
                next
               }
                                         # second file processing; if same Category and $3 between Min and Max, and $5 lower than before one, keep $5

               {for (i=1; i<=ML; i++)  if ($2 == Cat[i] &&
                                           $3 >= Min[i] &&
                                           $3 <= Max[i] &&
                                           $5 <  Low[i]) Low[i] = $5
               }
END                     {for (i=1; i<=ML; i++) print Line[i], Low[i]
                        }
' File-B File-A
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004

많은 설명이 필요하지 않습니다. 첫 번째 파일( NR == FNR)부터 시작하여 범주 및 범위/경계 값을 유지하고 첫 번째 읽기의 실제 값이 더 낮도록 Low 배열 요소를 설정합니다. 두 번째 파일을 처리할 때 위에 기록된 데이터 세트를 반복합니다. 새로 읽은 레코드가 항목과 동일한 카테고리를 갖고 $3이 Min과 Max 사이에 있고 $5가 이전에 얻은 레코드보다 낮은 경우 $5를 배열에 유지합니다 Low. 이 END섹션에서는 기록된 행과 얻은 Low값을 표준 출력으로 인쇄합니다.

답변2

any awk및 any를 사용하십시오 sort.

$ cat tst.sh
#!/usr/bin/env bash

sort -k5,5n -- "$1" |
awk '
NR==FNR {
    if ( !($3 in map) ) {
        keys[++numKeys] = $3
        map[$3] = $5
    }
    next
}
{
    for ( k=1; k<=numKeys; k++ ) {
        key = keys[k]
        if ( ($2 <= key) && (key <= $3) ) {
            print $0, map[key]
            next
        }
    }
}
' - "$2"

$ ./tst.sh 'File-A' 'File-B'
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004

중복된 $3 값이 있는 경우 위의 내용은 연관된 가장 낮은 $5 를 올바르게 사용합니다 File-A.

관련 정보