Chinaunix首页 | 论坛 | 博客
  • 博客访问: 132996
  • 博文数量: 41
  • 博客积分: 15
  • 博客等级: 民兵
  • 技术积分: 65
  • 用 户 组: 普通用户
  • 注册时间: 2012-12-11 16:17
文章分类
文章存档

2017年(1)

2016年(5)

2015年(8)

2014年(13)

2013年(10)

2012年(4)

我的朋友

分类: LINUX

2014-12-28 12:43:19

1)

文本:
A 155
A 15
A 17
A 18
A 19
A 20
A 100
A 100
A 101
A 102
B 1
B 4
B 6
B 7
B 8
C 55
C 56
C 70
C 71
C 72

要求连续的行用跨度表示:
A: 155 15 17-20 100-102
B: 1 4 6-8
C: 55-56 70-72



  1. awk '{
  2.     if(!length(a[$1]))
  3.         a[$1]=$2;
  4.     else{
  5.         n=$2-1;
  6.         if(match(a[$1],"\\<"$2"\\>"))next;
  7.         if(sub("-"n,"-"$2,a[$1]))next;
  8.         if(sub(n,n"-"$2,a[$1]))next;
  9.         a[$1]=a[$1]" "$2};
  10.     }END{
  11.         for(n=0;n++<asorti(a,b);) print b[n]": "a[b[n]];
  12. }' file
[解析]
利用数组来实现,当每个新的特征段落开始,a[$1] 的值为空时,把 $1 特征赋值给以它为下标的数组,这时候为了计算是否和上行的 $2 连续,我们设定一个变量为 n=$2-1 ;为了精确匹配我们这里使用了 match() 函数匹配动态正则的方法,(动态正则 )后面的两个替换是点睛之笔,大家演算一下就知道妙用了。最后用 for 循环打印出数组的值。佩服 jason680 的思路。



  1. awk '{
  2.     if($1==x){
  3.         if(index(i,$2))next;
  4.         if($2==y+1)
  5.             i=i"-"$2;
  6.         else
  7.             i=i" "$2;
  8.     }else{
  9.         if(NR>1){
  10.             gsub(/-[^ ]*-/,"-",i);
  11.             print i;
  12.             }
  13.         i=$1": "$2;
  14.         }
  15.     x=$1;
  16.     y=$2;
  17. }' file <(echo)
[解析]
这是非数组版,原理是判断这一行和上一行是否是连续的,然后根据需要来拼接字符串,最后把中间的替换掉,形成一个跨度显示。如果顺序是乱的还是预先排序好后管道给awk,sort -k1,1 -k2,2n file 。



  1. awk '{
  2.     if ($1==x){
  3.         if($2==y+1){
  4.             if(!i){
  5.                 i=!i
  6.                 printf "-"
  7.             }
  8.         }else if($2>y){
  9.             if(i){
  10.                 printf y
  11.                 i=!i
  12.             }
  13.             printf " "$2
  14.         }
  15.     }else{
  16.         if(i){
  17.             print y
  18.             i=!i
  19.         }else if(NR>1)print ""
  20.         printf $1": "$2
  21.     }
  22.     x=$1
  23.     y=$2
  24. }END{
  25.     if(i)print y
  26.     else print ""
  27. }' file



2)

cat file 
82 82
98 98
99 99
100 100
114 114
123 123
124 124


要求如果是连续的行,压缩成一行:
82 82
98 100
114 114
123 124



  1. awk 'NR>1{
  2.     if(x+1!=$1){
  3.         if(!z){
  4.             print x FS x
  5.         }else{
  6.             y=y"-"x;sub(/-.*-|-/," ",y);print y;z=0;y=""
  7.         }
  8.     }else{
  9.         y=length(y)?y"-"x:x;z=1
  10.     }
  11. }
  12. {x=$1}
  13. END{
  14.     if(z){
  15.         y=y"-"x;sub(/-.*-|-/," ",y);print y
  16.     }else{
  17.         print x FS x
  18.     }
  19. }' file
[解析]
这个思路可能有点复杂,不知道有没有更好的方法,就是如果是连续的把数字用“-”串起来,最后再统一替换掉中间的部分,就留下起始和结束的数字,就算是用快度表示了。




  1. awk '{if(num+1!=$1){if(num)printf num"\n"$1" ";else printf $1" "}num=$1}END{{print $1}}' file
[解析]
这是很棒的思路,利用错行打印。



  1. awk '$1!=b+1{if(NR>1)print a,b;a=$1}{b=$2}' file <(echo)
[解析]
更棒的思路。


3)
cat file
var   1
var   2
var   3
var   4
var   5
var   8
var   9
var   10
var   11
var   12
var   13
var   14
var   25
var   26
var   27
var   28
var   29
var   55
var   56
var   57
var   58
var   59
var   60
var   61
var   90
var   91

结果:
var 1-5
var 8-14
var 25-29
var 55-61
var 90-91




  1. awk 'NR>1{if($2!=x+1){print y"-"x;c=0}}{x=$2}!c++{y=$0}' file <(echo)



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