cat用于纵向拼接、paste用于横向对齐、join用于按字段关联;选错命令会导致结果错误,合并前须检查顺序、编码、行数及字段一致性。

cat 是最直接的命令,但“合并”这个词容易误导——你得先想清楚:是要**纵向拼接**(A 文件内容完,再接 B 文件),还是**横向对齐**(A 的第 1 行和 B 的第 1 行并成一行),又或是**按字段关联**(比如用用户名把两份数据连起来)。选错命令,结果就不是你要的。
用 cat 拼文件?顺序不对是最大坑
它不排序、不校验、不加标记,就是原样串起来。cat file1.txt file2.txt > merged.txt 看似简单,但实际出错最多:
- 通配符
*.log展开按字典序,file10.log会排在file2.log前面——日志时间线全乱 - 没加空行或文件名分隔,合并后根本分不清哪段来自哪个文件,调试时抓瞎
- 编码混用(比如一个 UTF-8 with BOM,一个纯 ASCII)会导致
awk或grep报invalid byte sequence - 大文件合并前不检查磁盘空间,写到一半失败,留下半截脏文件
稳妥做法:find . -name "data_*.csv" -print0 | sort -z | xargs -0 cat > merged.csv;加来源标记:awk 'FNR==1{print "\n=== " FILENAME " ==="} 1' file1.txt file2.txt > merged.txt
paste 合并列?行数不等会丢数据
它不是拼文件,是“肩并肩”贴行:paste file1.txt file2.txt 默认用 \t 分隔,第 1 行对第 1 行,第 2 行对第 2 行……短文件用空字段补,长文件多出来的行直接不要。
- 输出行数 = 较短文件的行数——这不是 bug,是设计。别指望它保留所有原始行
- 默认分隔符是制表符,不是空格;后续用
cut -f解析时,cut -d' '会切歪 - 想用逗号分隔,必须显式写
paste -d ',' file1.txt file2.txt,引号不能省 - 如果两文件行数差很多,先用
awk 'NR==FNR{a[NR]=$0;next} {print a[FNR], $0}' file1.txt file2.txt补空更可控
join 匹配合并?不排序等于白跑
它本质是文本版 INNER JOIN:join file1.txt file2.txt 只输出两文件中第一列值完全相等的那些行,并横向拼成一行。不匹配的行直接丢弃——不是漏了,是逻辑如此。
- 必须提前排序,且排序字段要和 join 键一致;
sort file1.txt > s1.txt && sort file2.txt > s2.txt && join s1.txt s2.txt - 字段含空格?加
-t ','或-t $'\t'显式指定分隔符 - 想保留没匹配上的行?加
-a 1(保留 file1 中无匹配的)或-v 2(只输出 file2 中无匹配的) - 输出为空?先跑
file -i file1.txt file2.txt看编码,再head -n5 file1.txt file2.txt对比字段值——首尾空格、大小写、BOM 都会导致不匹配
怎么选?看数据之间有没有“关系”
没关联字段(比如两段日志、两个配置片段),就用 cat;结构对齐、要并排对比(比如 IP 列 + 响应时间列),就用 paste;有公共键(比如 users.txt 和 orders.txt 都含 username),才轮到 join。硬用 join 处理无键文件,结果不可控;反过来,用 cat 去处理本该关联的数据,后续还得花三倍时间清洗。
真正麻烦的从来不是命令本身,而是合并前没人检查编码、行数、字段一致性——这些细节一漏,后面所有分析都建立在错误输入上。











