在两列上合并具有条件的两个文件

时间:2014-04-22 12:37:13

标签: perl awk

我有两个类型的文件:

FILE1.TXT

1 117458 rs184574713 rs184574713
1 119773 rs224578963 rs224500000
1 120000 rs224578874 rs224500045
1 120056 rs60094200 rs60094200
2 120056 rs60094536 rs60094536

FILE2.TXT

10  120200  120400  A   0   189,183,107
1   0       119600  C   0   233,150,122
1   119600  119800  D   0   205,92,92
1   119800  120400  F   0   192,192,192
2   120400  122000  B   0   128,128,128
2   126800  133200  A   0   192,192,192

我想将第二个文件中包含的信息添加到第一个文件中。两个文件中的第一列需要匹配,而File1.txt中的第二列应该落在File2.txt中第2列和第3列指示的间隔中。因此输出应如下所示:

1 117458 rs184574713 rs184574713 C  0   233,150,122
1 119773 rs224578963 rs224500000 D  0   205,92,92
1 120000 rs224578874 rs224500045 F  0   192,192,192
1 120056 rs60094200 rs60094200 F    0   192,192,192
2 120440 rs60094536 rs60094536 B    0   128,128,128

请帮助我使用awk / perl ..或任何其他脚本。

2 个答案:

答案 0 :(得分:2)

这是你在 bash 中做的事情(在 awk 的帮助下):

join -1 1 -2 1 \
        <(sort -n -k1,1 test1) <(sort -n -k1,1 test2) | \
        awk '$2 >= $5 && $2 <= $6 {print $1, $2, $3, $4, $7, $8, $9}'

这是一个简短的解释。

  1. 首先,我们使用join根据公共密钥( 第一场)。

  2. 但是join期望两个输入文件都已经排序(因此 sort)。

  3. 至少,我们使用awk来应用所需的条件,并且 投射我们想要的字段。

答案 1 :(得分:1)

试试这个:(考虑到输出中有最后一个输入的拼写错误。120056不在120400 122000之间。

$ awk '
NR==FNR {
    a[$1,$2,$3]=$4 FS $5 FS $6;
    next
}
{
     for(x in a) {
         split(x,tmp,SUBSEP); 
         if($1==tmp[1] && $2>=tmp[2] && $2<=tmp[3]) 
             print $0 FS a[x]
      }
}' file2 file1
1 117458 rs184574713 rs184574713 C 0 233,150,122
1 119773 rs224578963 rs224500000 D 0 205,92,92
1 120000 rs224578874 rs224500045 F 0 192,192,192
1 120056 rs60094200 rs60094200 F 0 192,192,192
  • 您通读了第一个文件,创建了一个在第1,2和3列索引的数组,其值为第4,5和第6列。
  • 对于第二个文件,您将在数组中查找。对于每个键,您将拆分键并检查第一列匹配的条件和第二列是否在范围内。
  • 如果条件为真,则从文件1打印整行,后跟数组值。