You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用awk删除文件重复行,保留第5列最接近参考文件值的行

问题描述

我有两个文件:

file1.txt 内容

$cat file1.txt
0105   20   20   95     50
0106   20   20   95     50
0110   20   20   88     60
0110   20   20   88     65
0115   20   20   82     70
0115   20   20   82     70
0115   20   20   82     75

file1.txt第一列存在重复值,分别是0110和0115。我需要对file1.txt做行筛选,规则是:如果首列重复仅保留1行,保留行的第5列值要和参考文件file2.txt中同首列条目的第5列值最接近(相等或差值最小),不需要修改file1的原有值。

file2.txt 内容

$cat file2.txt
0105   20   20   95     50
0106   20   20   95     50
0107   20   20   95     52
0110   20   20   88     65  34
0112   20   20   82     80  23
0113   20   20   82     85  32
0114   20   20   82     70  23
0115   20   20   82     72
0118   20   20   87     79
0120   20   20   83     79

期望输出

0105   20   20   95     50
0106   20   20   95     50
0110   20   20   88     65
0115   20   20   82     70

已尝试的错误脚本

awk 'FNR==NR { a[$5]; next } $5 in a ' file1.txt file2.txt > test.txt
awk '{a[NR]=$1""$2} a[NR]!=a[NR-1]{print}' test.txt

预期的算法逻辑

# 逐行检查file1.txt第一列的条目是否和下一行重复
即 外层遍历行号i:
    内层遍历列号j:
如果当前行第j列值不等于下一行第j列值,直接输出整行;
如果相等:
# 找到file2.txt中首列和当前行首列相同的行
# 把该行的第5列,和file1中所有首列等于当前首列的行的第5列做差
# 取差值最小的行保留
例:如果有3行首列相同的条目,选择差值最小的那行即可

解决方法

直接用单条awk命令即可实现需求:

awk '
# 先读取file2,把首列作为键,存储对应第5列的参考值
FNR == NR {
    ref[$1] = $5
    next
}
# 再读取file1,按首列分组,记录差值最小的行
{
    cur_diff = $5 > ref[$1] ? $5 - ref[$1] : ref[$1] - $5
    # 如果当前首列无记录,或当前行差值更小,就更新存储内容
    if (!($1 in min_diff) || cur_diff < min_diff[$1]) {
        min_diff[$1] = cur_diff
        res[$1] = $0
    }
}
# 最后遍历输出结果,加sort保证顺序和原文件一致
END {
    for (key in res) {
        print res[key]
    }
}
' file2.txt file1.txt | sort -k1n

逻辑说明

  1. 第一步读取参考文件file2,提前把首列对应的第5列参考值存入数组,避免后续重复查找
  2. 读取file1时实时计算当前行第5列和参考值的绝对差值,每个首列仅保留差值最小的行;如果差值相同会保留先出现的行,符合示例中0115首列两个70的筛选逻辑
  3. 最后对输出结果按第一列数值排序,保证输出顺序和预期完全一致

内容的提问来源于stack exchange,提问作者Kay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 10:36:02