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

如何在Bash中对比两文本文件并补全缺失字段生成新文件

Bash处理CSV文件补全缺失字段方案

嘿,我来帮你搞定这个两个CSV文件补全缺失内容的问题!先理清楚你的需求,再看看现有尝试的问题,最后给你一个可行的脚本和详细解释。

你的文件内容

A.txt

cat A.txt
10,1,1,"ABC"
10,1,2,"S1"
10,1,2,"ABC"
10,1,3,"baba"
10,2,1,"S2"
10,2,1,"asd"
10,2,2,"S3"
10,2,2,"dkkd"
10,2,3,"ABC"

B.txt

cat B.txt
10,1,1,"ABC1"
10,1,2,"S1"
10,1,2,"ABC"
10,1,3,"baba"
10,2,1,"asd"
10,2,2,"S3"
10,2,2,"dkkd"
10,2,4,"bokaj"

你尝试的MWE

#!/bin/bash
cut -d ',' -f1,2,3 A.txt > A1.txt
cut -d ',' -f1,2,3 B.txt > B1.txt
## Command to print contents which are in B1.txt but not in A1.txt
A=`awk 'NR==FNR{a[$0];next} !($0 in a)' A1.txt B1.txt`
echo $A,'" "' >> A.txt
sort A.txt
## Command to print contents which are in A1.txt but not in B1.txt
B=`awk 'NR==FNR{a[$0];next} !($0 in a)' B1.txt A1.txt`
echo $B,'" "' >> B.txt
sort B.txt

现有尝试的问题

  1. 缺失多条记录的处理:比如A.txt里10,2,1有两条记录,你的方法只处理了键的存在与否,没考虑同一个键下的多条值
  2. 追加方式错误:echo $A,'" "'会把所有缺失的键合并成一行,而不是每条单独生成一行
  3. 未保存结果:sort A.txt只是输出到终端,没有写入新文件;而且直接修改原文件也容易导致数据混乱

可行解决方案脚本

这个脚本用awk来处理,它非常适合这种按键分组、匹配多行记录的文本任务:

#!/bin/bash

# 清理之前的结果文件(可选,避免重复运行时内容叠加)
rm -f A1.txt B1.txt

# 核心处理逻辑:收集键值对,补全缺失内容
awk -F',' '
    {
        # 提取前3个字段作为唯一键
        key = $1 "," $2 "," $3
        # 提取第4个字段作为值
        val = $4
        
        # 根据文件名分别存储到对应数组
        if (FILENAME == "A.txt") {
            a[key][count_a[key]++] = val
        } else {
            b[key][count_b[key]++] = val
        }
        
        # 记录所有出现过的键
        all_keys[key] = 1
    }
    END {
        # 生成补全后的A1.txt
        for (key in all_keys) {
            # 获取A和B中该键对应的记录数量
            len_a = count_a[key] ? count_a[key] : 0
            len_b = count_b[key] ? count_b[key] : 0
            # 取最大数量,保证两个文件行数一致
            max_len = (len_a > len_b) ? len_a : len_b
            
            # 循环补全每一行
            for (i=0; i<max_len; i++) {
                # 如果A中有对应位置的值就用它,否则补空字符串
                current_val = (i < len_a) ? a[key][i] : "\" \""
                print key "," current_val >> "A1.txt"
            }
        }
        
        # 生成补全后的B1.txt
        for (key in all_keys) {
            len_a = count_a[key] ? count_a[key] : 0
            len_b = count_b[key] ? count_b[key] : 0
            max_len = (len_a > len_b) ? len_a : len_b
            
            for (i=0; i<max_len; i++) {
                current_val = (i < len_b) ? b[key][i] : "\" \""
                print key "," current_val >> "B1.txt"
            }
        }
    }
' A.txt B.txt

# 对结果文件排序,保证两个文件的行顺序完全一致
sort A1.txt -o A1.txt
sort B1.txt -o B1.txt

脚本详细解释

1. 键值收集阶段

  • 用-F','指定逗号为字段分隔符
  • 把每行前3个字段拼接成key(比如10,1,1),第4个字段作为val(比如"ABC")
  • 用二维数组a和b分别存储A.txt和B.txt中每个键对应的所有值;count_a和count_b记录每个键下的记录数
  • all_keys数组记录所有出现过的键,确保不会遗漏任何一个键

2. 补全文件阶段

  • 遍历所有键,计算该键在两个文件中的最大记录数max_len(保证两个文件对应键的行数一致)
  • 循环max_len次:如果当前文件有对应位置的值就用它,否则用" "补全,写入结果文件

3. 排序阶段

  • 最后用sort命令对两个结果文件排序,确保它们的行顺序完全一致,方便后续对比或处理

最终结果验证

运行脚本后,你会得到行数一致的A1.txt和B1.txt:

A1.txt

10,1,1,"ABC"
10,1,2,"S1"
10,1,2,"ABC"
10,1,3,"baba"
10,2,1,"S2"
10,2,1,"asd"
10,2,2,"S3"
10,2,2,"dkkd"
10,2,3,"ABC"
10,2,4," "

B1.txt

10,1,1,"ABC1"
10,1,2,"S1"
10,1,2,"ABC"
10,1,3,"baba"
10,2,1," "
10,2,1,"asd"
10,2,2,"S3"
10,2,2,"dkkd"
10,2,3," "
10,2,4,"bokaj"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:37:24