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

如何用awk基于多列比较两个CSV文件并找出差异行

用awk找出CSV中EMPLOYEE_NUMBER+EMAIL相同但其他列不同的行

我来帮你搞定这个CSV比对的需求!首先得明确核心目标:在两个大CSV文件(各5000行)里,找出那些EMPLOYEE_NUMBER和EMAIL_ADDRESS组合完全相同,但其他列存在差异的行,并且把这些有差异的行都列出来。

关键注意点:带引号的CSV字段

你的CSV里有带逗号的字段(比如"Example, Inc."),直接用awk默认的逗号分割会出错,所以得先设置正确的字段匹配规则,确保带引号的字段被当作一个整体处理。

解决方案1:固定列顺序版本

如果两个文件的列顺序完全一致,这个脚本可以直接用:

BEGIN {
    # 正确匹配带引号的CSV字段:要么是带引号的内容,要么是不含逗号的内容
    FPAT = "\"[^\"]*\"|[^,]*"
    OFS = ","
    header_printed = 0
}

# 处理表头,只打印一次
NR == 1 {
    if (!header_printed) {
        print $0
        header_printed = 1
    }
    next
}

{
    # 用EMPLOYEE_NUMBER和EMAIL_ADDRESS拼接成唯一键,用|分隔避免和字段内容冲突
    key = $1 "|" $9
    # 保存当前行的完整内容
    line = $0

    # 如果这个键已经存在,且存储的行和当前行不一样
    if (key in lines) {
        if (lines[key] != line) {
            # 先输出之前存储的行(确保只输出一次)
            if (!printed[key]) {
                print lines[key]
                printed[key] = 1
            }
            # 输出当前行
            print line
        }
    } else {
        # 第一次遇到这个键,保存行内容
        lines[key] = line
    }
}

解决方案2:动态列索引版本(更鲁棒)

如果两个文件的列顺序可能不同,这个版本会根据表头自动定位EMPLOYEE_NUMBER和EMAIL_ADDRESS的位置,适配性更强:

BEGIN {
    FPAT = "\"[^\"]*\"|[^,]*"
    OFS = ","
    header_printed = 0
}

# 处理表头,记录每个列名对应的索引
NR == 1 {
    for (i=1; i<=NF; i++) {
        col_index[$i] = i
    }
    if (!header_printed) {
        print $0
        header_printed = 1
    }
    next
}

{
    # 动态获取EMPLOYEE_NUMBER和EMAIL_ADDRESS的字段值
    emp_num = $col_index["EMPLOYEE_NUMBER"]
    email = $col_index["EMAIL_ADDRESS"]
    key = emp_num "|" email
    line = $0

    if (key in lines) {
        if (lines[key] != line) {
            if (!printed[key]) {
                print lines[key]
                printed[key] = 1
            }
            print line
        }
    } else {
        lines[key] = line
    }
}

怎么运行

把上面的脚本保存成compare_csv.awk,然后在终端运行:

awk -f compare_csv.awk file1.csv file2.csv

测试你的示例文件

用你提供的两个文件测试,输出会是:

EMPLOYEE_NUMBER,LAST_NAME,FIRST_NAME,MIDDLE_NAME,BRANCH,DEPARTMENT,LEVEL,POSITION,EMAIL_ADDRESS
2,Charles,Alex,Bernard,"Example, Inc.",Example 2 Department,Manager,Business,alex.charles@example.com
2,Charles,Alex,Bernard,"Example, Inc.",Example 2 Department,Supervisor,Business,alex.charles@example.com

(注:你之前给出的期望输出里两行内容相同是笔误,实际应该是这两行LEVEL列不同的记录)

脚本说明

  • FPAT:awk的这个变量用来定义字段的匹配规则,确保带引号的字段不会被逗号分割。
  • 表头只打印一次,避免重复输出。
  • 用EMPLOYEE_NUMBER+EMAIL_ADDRESS作为唯一键,确保我们只比对同一员工同一邮箱的记录。
  • 当遇到相同键但不同内容的行时,会把前后两行都输出,方便你对比差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:36:56