File1 有 8 列。第 3 列和第 4 列形成一对,如 rs|860 rs|756,与该对关联的值位于第 8 列。
bb yy rs|860 rs|756 xx aa 0.7 2234
bb yy rs|310 rs|260 xx aa 0.3 9838
bb yy rs|110 rs|77 xx aa 0.5 2291
bb yy rs|756 rs|860 xx aa 0.4 2269
bb yy rs|110 rs|77 xx aa 0.9 1112
bb yy rs|756 rs|860 xx aa 0.8 3269
bb yy rs|233 rs|79 xx aa 0.4 1397
bb yy rs|79 rs|233 xx aa 0.7 1397
列 3 和 4 或 4 和 3 的对应该被相同地对待,例如 rs|860 rs|756 == rs|756 rs|860。接下来,第一行中的对也可能出现在第 4 行和第 6 行中(相反)。简单地说,AB = BA = BA。首先,我想按行对 col3 和 col4 进行排序,这可以使数据像 AB = AB = AB 一样。接下来,在所有出现的对中,只有一个应该在第 8 列保留最大值。例如,rs|860 rs|756 在第 6 行处具有最大值(即 3269),因此应删除第 1 行和第 4 行。同样,在 rs|110 的情况下,应删除 rs|77 row5。接下来,如果在第 8 列有相似值的对,则应保留在第 7 列具有较高值的对。例如,如果是 rs|233 rs|79 row7,则应删除第 7 列值较低的值 (0.4)。对于任意一对,如果第 8 列和第 7 列都没有较高/较低差异,则可以删除任何一个。
所需的输出 File2
bb yy rs|260 rs|310 xx aa 0.3 9838
bb yy rs|77 rs|110 xx aa 0.5 2291
bb yy rs|756 rs|860 xx aa 0.8 3269
bb yy rs|79 rs|233 xx aa 0.7 1397
答案1
这是一个不优雅的awk
解决方案:
{
split($3, a, "|")
split($4, b, "|")
if (a[2] > b[2]){
$3=b[1]"|"b[2]
$4=a[1]"|"a[2]
}
split(arr[$3" "$4], c, " ")
if ($8 > c[8]){
arr[$3" "$4] = $0
}
}
END{
for (item in arr){
print(arr[item])
}
}
运行与
awk -f script.awk input
它不保留间距,并且顺序是随机的。
答案2
建立在pfnuesel 的回答,
{
split($3, a, "|")
split($4, b, "|")
if (a[2] > b[2]){
$3=b[1]"|"b[2]
$4=a[1]"|"a[2]
}
key=$3" "$4
split(arr[key], c, " ")
if ($8 > c[8] || ($8 == c[8] && $7 > c[7])){
arr[key] = $0
}
}
END{
for (item in arr){
print(arr[item])
}
}
如问题中所示(但未明确说明),这假设第三列和第四列中的值的形式为
一些_字符串|数字
其中空格仅供说明之用,并且细绳不包含任何|
字符。这些标记将根据数字s;这细绳不比较前缀。
如在pfnuesel 的回答,用法是
awk -f script.awk file1
输入文件的确切间距丢失,但可以通过管道通过(重新)创建可读的列间距 column -t
;例如,
awk -f script.awk file1 | column -t > file2