awk의 두 파일 사이의 열을 조건부로 비교합니다.

awk의 두 파일 사이의 열을 조건부로 비교합니다.

awk를 사용하여 예제를 찾아봤지만 여러 조건을 비교할 때 배열을 올바르게 사용하는 데 문제가 있습니다. 두 개의 파일이 있고 두 가지 조건이 충족되면 정보를 반환하고 싶습니다.

  1. 파일 2의 열 1(예: ScYwTfa_25)은 파일 1의 열 4(예: Y == Y)와 일치합니다.
  2. 파일 2의 열 2는 파일 1의 열 5보다 크거나 같지만 파일 1의 열 6보다 작거나 같습니다(예: Ymin < Y1 < Ymax)

파일 1의 열 5와 6은 위치 값 범위입니다. 파일 2의 위치가 해당 범위 내에 있으면 파일 1의 열 2와 3의 해당 값 범위에 매핑하고 새 위치를 반환하고 file1의 첫 번째 열을 반환하고 싶습니다. . 파일 1에서 열 5와 6의 범위는 열 2와 3의 범위와 길이가 동일하지만 열 4와 1에 명명된 좌표계는 다릅니다.

다음은 샘플 파일입니다.

파일 1

X  Xmin  Xmax  Y             Ymin     Ymax
10 27124 27153 ScYwTfa_25    11382070 11382099
10 41731 41779 ScYwTfa_10450 20433584 20433632
10 41780 41819 ScYwTfa_10450 20433544 20433583
10 41886 41916 ScYwTfa_10450 20433447 20433477
10 41917 41943 ScYwTfa_10450 20433420 20433446

파일 2

Y             Y1
ScYwTfa_25    11382075
ScYwTfa_10450 20433425
ScYwTfa_10450 20433430
ScYwTfa_10450 99999999

원하는 결과는 다음과 같습니다.

10 27129
10 41922
10 41927

결과를 생성하는 첫 번째 줄은 다음과 같습니다.ScYwTfa_25파일 2가 일치함ScYwTfa_25파일 1 AND 11382075(파일 2)에서 범위는 11382070~11382099(파일 1)입니다. 따라서 파일 1의 열 1이 인쇄되고(예: 10), 27129는 열 2와 3의 파일 1에 있는 새 범위에서 11382075의 위치를 ​​찾는 것을 기반으로 합니다(예: Xmin + (Y1 - Ymin) = 27124 + (11382075 - 11382070) = 27129).

마찬가지로 파일 2의 라인 2와 3은 파일 1의 마지막 라인에 해당하므로 출력이 생성됩니다. 그러나 파일 2의 마지막 줄은 ScYwTfa_10450에 파일 1에 일치하는 항목이 여러 개 있더라도 위치 99999999가 해당 Y에 대한 Ymin~Ymax 범위 내에 있지 않기 때문에 출력을 생성하지 않습니다.

이 예가 잘 설명되기를 바랍니다. NR == FNR 접근 방식을 사용하려고 노력했지만 서로 다른 파일 간의 정보를 연관시키는 데 awk를 많이 사용하지 않았습니다.

미리 감사드립니다.

매트

답변1

awk '
  FNR==1{ next }                          # skip header on file2, file1
  FNR==NR{                                # if file2...
    y[$1]=(y[$1]=="" ? "" : y[$1] FS) $2  # append Y1-values FS-separated to array `y`
    next                                  # continue with next record
  }
                                          # if file1...
  ($4 in y){                              # col4 matches col1 of file2
    n=split(y[$4], y1)                    # split Y1-values into array `y1`
                                          # of length n (using FS as separator)
    for (i=1;i<=n;i++)                    # loop over y1 values
      if ($5<=y1[i] && y1[i]<=$6)         # Y1 in range?
        print $1, ($2 + (y1[i] - $5))     # print result
  }
' file2 file1

관련 정보