我有一些文件如下所示
GLL ALM 654-656 654 656
SEM LYG 655-657 655 657
SEM LYG 655-657 655 657
ALM LEG 656-658 656 658
ALM LEG 656-658 656 658
ALM LEG 656-658 656 658
LEG LEG 658-660 658 660
LEG LEG 658-660 658 660
GLL的值为654.ALM的值为656.同样,第4列表示第一列的值。第5列表示第二列的值。我想计算第四和第五列中每个数字的唯一出现次数。
期望的输出
654 GLL 1
655 SEM 1
656 ALM 2
657 LYG 1
658 LEG 2
660 LEG 1
答案 0 :(得分:1)
如果我理解你的问题,这个脚本可以给你输出:
awk '{d[$4]=$1;d[$5]=$2;p[$4];l[$5]}
END{
for(k in p){
if (k in l){
delete l[k]
print k,d[k],"2"
}else
print k,d[k],"1"
}
for (k in l)
print k, d[k],1
} ' file
用你的输入数据,上面脚本的输出:
654 GLL 1
655 SEM 1
656 ALM 2
658 LEG 2
657 LYG 1
660 LEG 1
因此它与预期的输出(订单)不是100%相同,但是如果你把它传递给sort -n
,它会给你完全相同的东西。排序部分也可以在awk内完成。我有点懒...:)
答案 1 :(得分:0)
对不起,它太长了,但它有效并且如果发生了这样的事情,它会内置奖励!有关详细信息,请参见编辑2。 : - )
awk '
BEGIN { SUBSEP = FS;
before = 0;
between = 1;
after = 0;
}
{
offset = int((NF - after - before - between) / 2) + between;
for (i=1 + before; i <= offset + before - between; i++) {
j = i + offset;
if (! ((i, $j, $i) in entry))
entry[i, $j, $i]++;
}
}
END {
for (item in entry) {
split(item, itema);
entry[itema[2], itema[3]]++;
delete entry[item];
}
for (item in entry)
print item, entry[item];
}' filename | sort -n
第一部分过滤输入,仅接受应该在输出的第一列和第二列中的唯一出现的对。第二部分结合了结果,在一个唯一的列中每次出现增加1(例如LEG,658在$ 1,$ 4和$ 2,$ 5中至少出现一次,因此它被计算两次),并打印结果,通过使用sort实用程序以数字方式对输出进行排序。
它是针对N对进行推广的,所以如果你将来有类似的东西,那么脚本仍然可以工作,只要添加了对(你不能添加另一个单独的字段,或者脚本中断):
GLL ALM LEG 654-660 654 656 660
我想如果你想,你可以在开头添加额外的字段并改变i的起始值。或者可以在最后添加,并为您添加的每个新字段从i的结束值中减去一个(例如,如果在末尾添加1个不成对的字段,则为NF - 2)。它需要重新设计以适应中间的不成对值,因为数据集将完全不同。
修改强> 它只有这么长时间,因为它很灵活(有点),因为我仍然是一个awk新手。如果你不喜欢我的话,我会推荐Kent's(或者它不起作用 - 我现在没有使用安装了awk的电脑)。
编辑2 更新的脚本。它之前没有用,它现在可以处理任意偏移,只要没有不成对的字段将对分开。类似下面的工作:
GLL ALM LYG 654-657 654 656 657
SEM LYG 655-657 655 657
SEM LYG LEG 655-660 655 657 660
ALM LEG 656-658 656 658
LEG LEG 658-660 658 660
LYG LEG 657-660 657 660
输出:
654 GLL 1
655 SEM 1
656 ALM 2
657 LYG 3
658 LEG 2
660 LEG 2
编辑3 该脚本现在处理任意连续不成对字段。您必须在对的第一部分开始之前配置有多少个字段(例如,第一个GLL,ALM之前的字段数等),之间有多少个字段对的第一部分和第二部分,以及在对的第二部分列表之后的字段数。请注意,它必须是连续且一致的,这意味着在一行的第一对启动组件和另一行的第一对启动组件之前的5个字段之前,您不能拥有类似1字段的内容,并且您不能有一对启动/ end组件与另一组件分离(例如“GLL xyz ALM 654 656”不起作用,因为“xyz”分隔“GLL”和“ALM”,它们都是成对启动组件)。
除此之外,还需要有关数据集的实际知识,例如GLL可能在其后立即有额外信息,但ALM不会有这样的数据。
答案 2 :(得分:0)
我的看法:
sort -u file |
awk '
BEGIN {SUBSEP = OFS}
{count[$4,$1]++; count[$5,$2]++}
END {for (key in count) print key, count[key]}
' |
sort -n
654 GLL 1
655 SEM 1
656 ALM 2
657 LYG 1
658 LEG 2
660 LEG 1