1)
文本:
b 9 12
h 76 83
a 5 7
d 25 35
e 39 43
f 60 63
j 97 99
i 84 87
c 15 19
k 102 107
l 109 120
g 67 72
第一列是线段名称,第二、三列是线段的起点和终点,线段之间没有重叠,文件中线段是无序的,如果连续的两条线段之间距离小于6,就说他们相邻,如果相邻线段数大于2就说这些线段形成连续块,要求打印出所有连续的块:
- awk 'NR>1{if($2-y<6 && $2-y>0){i=i?i"-"$1:x"-"$1;z++}else{if(z>1)print i;i=0;z=0}};{x=$1;y=$3}' <(sort -k2n file;echo)
[解析]
首先得按照第一列的名称来排序,第一行,就不比较了,执行第二个{action},然后第二行满足 NR>1 条件,开始执行比较,看当前行的开始点减上一行的终止点,结果是否小于6,为什么还要判断是否大于0,我们稍候讲,满足这个条件后来判断 i 的值是否为空,然后按条件给 i 赋值。然后执行 z++ 记数,直到超出我们的判断条件后,判断是否 z>1 ,这样的目的就是来看是否是3个线段,如果只是2个线段相邻的就不打印了,然后把 i 和 z 都清空。直到最后我们 echo 打印的空行,这时候空行的 $2 为空,即为零,去减上一行会存在负数,所以我们在 if 判断里会加上大于0的判断,这样不满足条件,迫使流程去执行 else 里的 if 判断,看是否我们的计数器 z 大于1,大于1我们才能判断是两个以上的相邻线段,才能打印 i 里保存的数据。
- sort -k2n file|awk 'function p(){if(k>2)print r}{a[NR]=$3;if(NR==1 || $2-a[NR-1]>=6){p();r=$1;k=1}else{r=r"-"$1;k++}}END{p()}
[解析]
这条命令利用了函数,专门用一个函数来判断是否是相邻的两个以上的线段,然后才会打印。首先用数组保存第三列的值,然后满足第一行或当前行的第二列减上一行的第三列大于等于6,就执行函数里的判断,不满足条件呢就进行 r 的字符串拼接,和 k++。最后 END 也再执行一次函数,判断是否满足条件打印。
- awk '{name[$2]=$1;left[$1]=$2;right[$1]=$3}END{
-
x=asort(left);
-
asort(right);
-
y=1;
-
s=name[left[1]];
-
for(i=2;i<=x;i++) {
-
if(left[i]-right[i-1]>=6) {
-
if(i-1>y+1)
-
print s;
-
y=i;
-
s=name[left[i]];
-
} else {
-
s=s"-"name[left[i]];
-
}
-
}
-
if(y<x-1)
-
print s;
-
}' file
2)
cat file
2012/01/10-11:10:27 2012/01/10-11:10:27 AA
2012/01/10-11:10:27 2012/01/10-11:20:27 BB
2012/01/10-11:10:27 2012/01/10-11:30:27 CC
要求把第二个时间大于等于第一个时间十分钟的行输出:
- awk 'function s(a){split(a,b,"-");cmd="date -d \""b[1]" "b[2]"\" +%s";cmd|getline line;close(cmd);return line};s($2)-s($1)>=600' file
[解析]
定义一个函数来计算时间戳,最后把这两个时间戳想减,大于600秒的打印。
阅读(3368) | 评论(0) | 转发(0) |