awkの2つのファイル間の列を条件付きで比較します。

awkの2つのファイル間の列を条件付きで比較します。

私はawkを使って例を見つけましたが、複数の条件を比較するときに配列を正しく使用するのに問題があります。 2つのファイルがあり、2つの条件が満たされている場合は、情報を返したいと思います。

  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

関連情報