unix 文件1中的Awk列值在文件2中的两列范围内

n9vozmp4  于 2022-11-04  发布在  Unix
关注(0)|答案(1)|浏览(191)

我根据评论修改了问题。
我想匹配两个文件:如果文件1中的$4在文件2中的$3和$4范围内,我将打印文件1和文件2中的$6。如果没有匹配项,我将在输出中打印NA。如果有重叠范围,我将打印第一个匹配项(基于文件1的$4排序)。
档案一:
档案二:

18  16  8674587 8784575 +   ABAT
10349   17  69148007    69244815    -   ABCA10
23461   17  69244435    69327182    -   ABCA5

输出量:
我根据以前的答案尝试了以下方法,但没有成功。输出是一个空文件。

awk 'FNR == NR { val[$1] = $4 }
     FNR != NR { if ($1 in val && val[$1] >= $3 && val[$1] <= $4)
                     print $1, val[$1], $6
               }' file1 file2 > file3
hwamh0ep

hwamh0ep1#

假设条件:

  • 在多个匹配的情况下,OP已经声明,我们仅使用'first'匹配; OP还没有定义'first',所以我假设它是指file2中各行出现的顺序(也就是行号)

一个awk创意:

awk '
FNR==NR { min[++n]=$3                                # save 1st file values in arrays; use line number as index
          max[n]=$4
          col6[n]=$6
          next
        }
        { for (i=1;i<=n;i++)                         # loop through 1st file entries
              if (min[i] <= $4 && $4 <= max[i]) {    # if we find a range match then ...
                 print $0, col6[i]                   # print current line plus column #6 from 1st file and then ...
                 next                                # skip to next line of input; this keeps us from matching on additional entries from 1st file
              }
          print $0, "NA"                             # if we got here there was no match so print current line plus "NA"
        }
' file2 file1

**注意:**请记下输入文件的顺序;第一个答案(下面)是基于file1 file2的输入;此答案要求翻转输入文件的顺序,即file2 file1

这将生成:

**注:**以下内容基于OP的原始问题和预期输出(修订版#2); OP已经将预期输出修改到这样一种程度,即下面的答案不再有效...

假设条件:

  • file1中,rs575272151 / 69244805rs544419019 / 69244469均匹配来自file2的2个不同(重叠)范围,但是OP在预期输出中仅示出了一组匹配;从这一点我会假设...
  • 一旦找到来自file1条目的匹配,就从任何附加匹配中移除所述条目;这将消除file1条目的多个匹配项
  • 一旦找到来自file2的行的匹配,则停止寻找该行的匹配(即,转到来自file2的下一个输入行);这将消除file2的多个匹配
  • OP未提供有关如何确定要保留的多匹配项的任何详细信息,因此我们将使用找到的第一个匹配项

一个awk创意:

awk '
FNR==NR { val[$2]=$4; next }
        { for (i in val)                            # loop through list of entries from 1st file ...
              if ($3 <= val[i] && val[i] <= $4) {   # looking for a range match and if found ... 
                 print $0,i                         # print current line plus 2nd field from 1st file and then ...
                 delete val[i]                      # remove 1st file entry from further matches and ... 
                 next                               # skip to next line of input from 2nd file, ie, stop looking for additional matches for the current line
              }
        }
' file1 file2

这将生成:

18  16  8674587 8784575 +   ABAT rs537182016
10349   17  69148007    69244815    -   ABCA10 rs575272151
23461   17  69244435    69327182    -   ABCA5 rs544419019

备注:

  • 不保证for (i in val)构造以一致的方式处理数组条目;最终结果是,在存在多个匹配的情况下,我们简单地匹配由awk提供的“第一”数组条目;如果for (i in val)的这种“随机”性质是不可接受的,那么OP将需要用关于如何处理多个匹配的附加细节来更新问题
  • 对于这种特殊情况,我们实际上生成了与OP预期相同的输出,但rs575272151rs544419019的赋值可以很容易地颠倒(由于for (i in val)结构的性质)

相关问题