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

UNIX下对比两平面文件指定字段(数值格式不同)求助

嘿,这个金额格式不统一的对比问题确实有点棘手,不过咱们先把两边的金额字段统一成相同格式,之后对比就轻松多啦!结合你已经用cut提取好目标字段的情况,给你几个实用的解决方案:

方法1:用awk统一金额格式后对比(最靠谱的数值处理方式)

因为awk可以直接把金额字符串转成数值,自动处理各种格式差异(比如-0、1、1.2这些),再统一格式化为两位小数,完美匹配文件2的格式。

重要提醒:你用cut -d '|' -f 1-45,56,67-174提取后,原来的第56位金额字段现在变成了cut结果里的第46位(前面1-45是45个字段),下面的命令都是基于这个位置来的。

首先,你可以把两个cut后的文件统一格式后存成临时文件,再用diff对比:

# 处理cut后的文件1,统一金额为两位小数
awk -F'|' '{
    normalized_amt = sprintf("%.2f", $46 + 0)
    # 重新拼接整行,替换金额字段
    line = $1
    for (i=2; i<=NF; i++) {
        if (i == 46) line = line "|" normalized_amt
        else line = line "|" $i
    }
    print line
}' cut_file1 > normalized_file1

# 同样处理cut后的文件2
awk -F'|' '{
    normalized_amt = sprintf("%.2f", $46 + 0)
    line = $1
    for (i=2; i<=NF; i++) {
        if (i == 46) line = line "|" normalized_amt
        else line = line "|" $i
    }
    print line
}' cut_file2 > normalized_file2

# 对比两个格式化后的文件
diff normalized_file1 normalized_file2

如果不想生成临时文件,可以用shell的进程替换直接对比:

diff <(awk -F'|' '{
    normalized_amt = sprintf("%.2f", $46 + 0)
    line = $1
    for (i=2; i<=NF; i++) {
        if (i == 46) line = line "|" normalized_amt
        else line = line "|" $i
    }
    print line
}' cut_file1) <(awk -F'|' '{
    normalized_amt = sprintf("%.2f", $46 + 0)
    line = $1
    for (i=2; i<=NF; i++) {
        if (i == 46) line = line "|" normalized_amt
        else line = line "|" $i
    }
    print line
}' cut_file2)

方法2:直接用awk对比并输出不匹配记录

如果你的两个文件是按某个唯一关键字(比如第一个字段)一一对应的,这个方法能直接输出不匹配的记录,比diff更直观:

awk -F'|' 'NR==FNR {
    # 先读取第一个文件,把格式化后的整行存在数组里,用第一个字段当索引
    normalized_amt = sprintf("%.2f", $46 + 0)
    line = $1
    for (i=2; i<=NF; i++) {
        if (i == 46) line = line "|" normalized_amt
        else line = line "|" $i
    }
    records[$1] = line
    next
}
{
    # 读取第二个文件,格式化后和第一个文件的记录对比
    normalized_amt = sprintf("%.2f", $46 + 0)
    line = $1
    for (i=2; i<=NF; i++) {
        if (i == 46) line = line "|" normalized_amt
        else line = line "|" $i
    }
    if (records[$1] != line) {
        print "⚠️  Mismatch for key " $1 ":"
        print "File1: " records[$1]
        print "File2: " line
        print "-------------------------"
    }
}' cut_file1 cut_file2

方法3:用sed做字符串替换统一格式(适合简单场景)

如果你确定金额格式只有你提到的几种(比如整数、一位小数、-0),也可以用sed做字符串替换来统一格式,不过这种方法不如awk的数值处理可靠,万一有特殊格式容易出错:

# 处理文件1的cut结果:把整数补成.00,一位小数补成两位,-0/-0.0换成0.00
sed -E '
    s/([^|]+)\|(-?[0-9]+)(\|)/\1|\2.00\3/g;
    s/([^|]+)\|(-?[0-9]+\.[0-9])(\|)/\1|\20\3/g;
    s/([^|]+)\|-0(\.0?)?(\|)/\1|0.00\3/g
' cut_file1 > normalized_file1

# 文件2的格式已经是两位小数,直接用原cut结果或者也做个兜底处理
sed -E 's/([^|]+)\|(-?[0-9]+\.[0-9]{2})(\|)/\1|\2\3/g' cut_file2 > normalized_file2

# 对比
diff normalized_file1 normalized_file2

记得替换命令里的cut_file1和cut_file2为你实际的文件名哦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:03:17