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

Bash入门者求助:如何用Awk合并CSV中第二列相同的行

解决CSV按第二列合并行并保留第三列的Awk方案

嘿,我来帮你搞定这个问题!你的核心思路是对的,但问题出在没有单独存储第三列(Value)的信息——原来的代码只跟踪了合并后的Name,所以输出时要么拿不到Value,要么错误地重复了Name内容。

问题分析

你原来的代码里,数组a[$2]只存了合并后的Name字符串,完全没保存对应的Value。当你在END块里想输出第三列时,错误地用了a[i](也就是Name)来填充,自然会重复显示第一列内容。

而且题目里明确说了“当两行的第二列相同时,第三列也必然相同”,这意味着我们只需要在第一次遇到某个Num时保存对应的Value就行,后续不用更新。

修改后的Awk代码

这里用两个数组分别跟踪合并后的Name和对应的Value:

BEGIN{FS=","; OFS=","}
NR==1{print; next}
{
    # 处理Name列的合并:如果已存在则追加,否则初始化
    names[$2] = ($2 in names) ? names[$2] " " $1 : $1
    # 仅在第一次遇到该Num时保存对应的Value
    if (!($2 in values)) {
        values[$2] = $3
    }
}
END{
    # 遍历所有Num,输出合并后的结果
    for (num in names) {
        print names[num], num, values[num]
    }
}

代码解释

  1. BEGIN块:设置输入分隔符FS和输出分隔符OFS为逗号,这样输出时自动用逗号分隔列,不用手动拼接,。
  2. 表头处理:第一行直接打印表头,然后next跳过后续逻辑。
  3. 主体逻辑:
    • 对于每一行,检查当前Num($2)是否已经在names数组中:如果是,就把当前Name($1)用空格追加到已有内容后;如果不是,就初始化names[$2]为当前Name。
    • 同时,如果这个Num还没在values数组里,就把对应的Value($3)存进去——因为题目保证相同Num的Value一致,所以只需要存一次。
  4. END块:遍历所有存储的Num,按顺序输出合并后的Name、Num、Value。

简化版代码(用三元表达式)

如果喜欢更简洁的写法,可以把主体逻辑压缩成一行:

BEGIN{FS=","; OFS=","}
NR==1{print; next}
{
    names[$2] = ($2 in names) ? names[$2] " " $1 : $1
    !($2 in values) && (values[$2] = $3)
}
END{for (num in names) print names[num], num, values[num]}

测试结果

用你的示例输入运行这段代码,会得到完全符合预期的输出:

Name,Num,Value
ex1 ex4,10.20.30.40,val1
ex2 ex5,20.30.40.30,val2
ex3,10.45.60.20,val3

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 23:02:27