抱歉,它太长了,但是如果发生这种情况,它可以工作并且内置奖励!有关详细信息,请参阅编辑 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 等之前有多少个字段),对的第一部分和第二部分之间有多少个字段,以及后面有多少个字段对的第二部分的列表。请注意,它必须是连续且一致的,这意味着您不能在一行的第一对开始组件之前有 1 个字段,在另一行的第一对开始组件之前不能有 5 个字段,并且您不能有一对开始/end 组件与另一个相同的组件分开(例如,“GLL xyz ALM 654 656”不起作用,因为“xyz”将“GLL”和“ALM”分开,它们都是对开始组件)。
除此之外,还需要有关数据集的实际知识,例如 GLL 是否可能紧随其后有额外的信息,但 ALM 从来没有这样的数据。