Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1059847
  • 博文数量: 186
  • 博客积分: 4939
  • 博客等级: 上校
  • 技术积分: 2075
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-08 17:15
文章分类

全部博文(186)

文章存档

2018年(1)

2017年(3)

2016年(11)

2015年(42)

2014年(21)

2013年(9)

2012年(18)

2011年(46)

2010年(35)

分类: 系统运维

2014-05-12 13:49:31


      链接如上,我误入perl版,技痒难忍,这分明是awk的经典问题啊,遂写了这个blog。具体要求见原帖,不过可以简述为:文件f1/f2第1列是ID,ID有很多个,第2和3列分别是坐标的起点/终点。现在以f1作为参考系,如果f2的坐标范围落在第一个相同ID的某一段的话(简称相交,e.g f1是[X,Y];如果f2的start/end在[X,Y]内(含边界)),就把该坐标从f1中去掉。简单举例如下:
f1 :
a  1 100
=============
f2:
a 3 7
由于f2的坐标落在f1的1 100范围内(ID也相同),那么此时要把3 7从 1 100去掉,分解为a 1 2和a 8 100,以此类推。当然这是很简单的情况,f2可能还有一行a 20 50,那么此时f1的a 8 100会继续分解为a 8 19 和a 51 100。怎么样看的头晕了吧?拿出纸笔画一下直线,划分一下范围就明白了。
简单测试数据如下,具体数据可以看原帖我回复的部分。

[user@myhost tmp]$ more d

A   1  10000
B   1  10001
B   10001  40000
a   2 5
x  10 10
c 1 3
d 5 6

[user@myhost tmp]$ more c
 
A   5        55
A   56        56
A   57        57
A   1024        1024
A   1025        1078
A   2047        2047
A   6658        6670
A   6671        6671
B   247        249
B   1024        1078
B   5547        5591
B   15547      25591
a 2 2
a 5 5
b 3 9
c 1 1
d 3 5
x 9 10

代码如下,复杂的逻辑关系,慢慢分析吧,已经经过严格测试,逻辑关系应该是没问题的。
awk 'NR == FNR{
 

                a[$1" "$2" "$3]=$1 }
 

        NR>FNR{
 

                  for(i in a)
 

                      {   flag=0
 

                         if(a[i]==$1)
 

                         {
 

                         split(i ,b ," ")

                        if($2 <= b[2] && $3 >= b[3])    

                                flag= 1

                        if ($2 >b[2] && $3 < b[3] )
                        { 

                               a[a[i]" "b[2] " "($2 - 1)] =a[i]

                                a[a[i]" "($3 + 1) " " b[3]] =a[i]
 

                                flag=1
 

                        }

                        if ($2 > b[2] && $2 <= b[3] && $3>=b[3])
 

                        {

                                a[a[i]" "b[2] " "($2 - 1)] = a[i]
 

                                flag= 1
 

                        }


                        if ($3 >= b[2] && $3 < b[3] && $2<= b[2])
 

                        {

                                a[a[i]" "($3 + 1) " " b[3]] = a[i]
 

                                flag= 1
 

                        }


                           }
 

                        if (flag)
 

                                delete a[i]
 

                      }
 

             }
 

END {
 

     for(i in a)print  i
 

   }' f1 f2

注意要把$1,$2,$3做index防止ID不同,但坐标范围相同冲掉上一个index的情况,此外,当split之后,必须要加上a[i],否则数组长度是2,2次分裂的时候出现b[3]为空的情况。

阅读(1083) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~