0

我在 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

帮我解决这个脚本.....

4

1 回答 1

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,lastprev(序列的开始、序列的结束和用于监视序列的前一行。它还将当前计数设置为1并返回处理第二个线。

$0 == prev+1在所有后续行中,如果当前行比上一行多一个,则触发第二部分。在这种情况下,它只是更新lastprev值和增量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
于 2013-09-15T06:10:32.220 回答