我在a.txt文件中输入了
10000030
10000029
10000028
10000027
10000026
10000024
10000023
10000021
10000018
10000018
10000017
10000016
10000015
10000014
10000013
10000011
10000010
10000009
10000008
10000006
10000005
10000004
10000003
10000002
10000001
我需要将连续的输入组合在一起,例如:
10000001,10000006,6
10000008,10000011,4
10000013,10000019,7
10000021,10000021,1
10000023,10000024,2
10000026,10000030,5
帮我解决这个脚本.....
答案 0 :(得分:2)
首先,您的输入数据似乎有拼写错误。为了获得您想要的输出,首先10000018
应为10000019
。
修复后,您可以通过以下awk
脚本传递已排序的文件来获得所需的输出:
NR==1 {
first = $0;
last = $0;
prev = $0;
count = 1;
next;
}
$0 == prev+1 {
last = $0;
prev = $0;
count++;
next;
}
{
print first","last","count;
first = $0;
last = $0;
prev = $0;
count = 1;
}
END {
if (count > 0) {
print first","last","count
}
}
调用该脚本data.awk
并将您的数据放入data.in
,结果如下:
pax> sort data.in | awk -f data.awk
10000001,10000006,6
10000008,10000011,4
10000013,10000019,7
10000021,10000021,1
10000023,10000024,2
10000026,10000030,5
阐述awk
脚本的工作原理。对于第一个输入行NR == 1
,它只是将当前值存储到first
,last
和prev
(序列的开头,序列的结尾和前一个)用于监控序列的行。它还将当前计数设置为1
,然后返回处理第二行。
在所有后续行中,如果当前行比前一行多一个,则会触发第二部分$0 == prev+1
。在这种情况下,它只是更新last
和prev
值并递增count
,然后返回到顶部以处理下一行。
因此,第三部分将触发前两部分未捕获的任何情况。这是输入文件中除第一行以外的任何记录,其中行不是一行加上前一行。换句话说,当开始新序列时。它首先打印出最新序列的详细信息,然后复制我们在第一部分中所做的内容。
处理完所有行后,END
部分将触发,输出最终序列的详细信息。请注意,仅当count
大于零时才输出。如果count
为零,那么该文件为空,因此根本没有序列。
还有一个略短的变体,它依赖于一些额外的条件,连接线条,以及这些部分按顺序处理的事实:
NR > 1 && $0 == prev+1 {
last = $0; prev = $0; count++;
next;
}
{
if (NR != 1) { print first","last","count; }
first = $0; last = $0; prev = $0; count = 1;
}
END {
if (count > 0) { print first","last","count }
}
当然,超短(且可读性差)命令行变量:
pax> sort data.in | awk 'NR>1&&$0==pr+1{ls=$0;pr=$0;ct++;next}{if(NR!=1){print fr","ls","ct}fr=$0;ls=$0;pr=$0;ct=1}END{if(ct>0){print fr","ls","ct}}'
10000001,10000006,6
10000008,10000011,4
10000013,10000019,7
10000021,10000021,1
10000023,10000024,2
10000026,10000030,5