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

如何使用awk按首字段合并多行指定字段并实现去重排序

问题场景

现有分号分隔的文本文件data.file,需按每行第一个字段为分组键合并重复行,规则如下:

  • 同组第2字段:剔除重复值、排序后用短横线-连接
  • 同组第3字段:取值固定,直接保留
  • 同组第4字段:剔除重复值、按数值升序排序后用短横线-连接
  • 同组第5字段:仅保留首次出现的取值
    原有使用getline逐行拼接的awk逻辑未做分组、去重、排序处理,存在行串行、值重复、顺序错乱问题,无法得到预期结果。
正确awk实现代码
awk -F';' '
!seen[$1]++ {
    lang[$1] = $3
    status[$1] = $5
    order[++total] = $1
}
{
    col2[$1,$2] = 1
    col4[$1,$4+0] = 1
}
END {
    for (i=1; i<=total; i++) {
        city = order[i]
        # 处理第2字段
        delete c2_arr
        c2_cnt = 0
        for (key in col2) {
            split(key, tmp, SUBSEP)
            if (tmp[1] == city) c2_arr[++c2_cnt] = tmp[2]
        }
        asort(c2_arr)
        c2_str = arr_join(c2_arr, c2_cnt, "-")

        # 处理第4字段
        delete c4_arr
        c4_cnt = 0
        for (key in col4) {
            split(key, tmp, SUBSEP)
            if (tmp[1] == city) c4_arr[++c4_cnt] = tmp[2] + 0
        }
        asort(c4_arr, "@val_num_asc")
        c4_str = arr_join(c4_arr, c4_cnt, "-")

        print city ";" c2_str ";" lang[city] ";" c4_str ";" status[city]
    }
}
function arr_join(arr, len, sep,    res, idx) {
    res = arr[1]
    for (idx=2; idx<=len; idx++) res = res sep arr[idx]
    return res
}
' data.file
逻辑说明
  • 逐行遍历阶段:
    • 用seen数组标记分组是否首次出现,首次出现时记录该组第3、第5字段的取值,同时记录分组首次出现的顺序,保证最终输出顺序和原文件一致
    • 利用awk关联数组的键唯一性自动对第2、第4字段去重,无需额外编写重复判断逻辑
  • 收尾处理阶段:
    • 按记录的分组顺序逐个处理每个城市的字段
    • 第2字段按字符串规则排序,第4字段指定按数值升序排序,避免字符串排序导致99排在33前面的问题
    • 自定义数组拼接函数,将排序后的字段值用-连接
    • 按要求的分号分隔格式拼接输出
运行结果

执行上述代码后将输出完全符合预期的结果:

Istanbul;J;TK;13;OK
London;C-K;EN;28-32;OK
Paris;A-B;FR;30-40;OK
Zurich;G-H;DE;33-82-99;OK

内容的提问来源于stack exchange,提问作者Andrés Chandía

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:30:39