提到Linux下的文本处理,大多数人首先想到的是grep、awk、sed这三大件,而paste命令往往被忽略。其实paste的功能非常单纯:把文件按列拼起来,或者把行串起来。别小看这个简单的功能,在处理CSV数据、日志对齐、批量生成配置等场景中,paste经常能用一行命令顶替一段awk脚本。这篇文章就把paste的语法、典型用法和容易踩的坑一次讲清楚。

paste命令的基本语法与默认行为
paste的标准语法是 paste 选项 文件1 文件2 ...,最简单的用法就是给两个文件,它会把文件1的内容放左边、文件2的内容放右边,逐行对齐合并。默认情况下,paste使用制表符Tab作为列之间的分隔符,这也是它名字的由来,就像把两张纸并排粘在一起。比如有两个文件,a.txt内容是三行数字,b.txt内容是三行字母,执行paste a.txt b.txt,输出的每一行就是数字加Tab再加字母。
直接看例子最直观。假设a.txt内容为1、2、3各占一行,b.txt内容为apple、banana、cherry各占一行,合并结果如下:
$ cat a.txt 1 2 3 $ cat b.txt apple banana cherry $ paste a.txt b.txt 1 apple 2 banana 3 cherry
有个细节值得注意:当两个文件行数不相等时,paste并不会报错,短的那个文件用完之后,后面缺的位置会以空Tab补齐。也就是说,长文件剩下的行仍然会输出,只是右侧是空的。这个行为通常符合预期,但如果你以为行数不齐会中断或报错,就可能在脚本里漏掉对数据完整性的检查。
另外,paste也支持从标准输入读取。如果只给一个减号作为文件名参数,paste会从stdin读取内容,这在管道组合里非常有用,比如 cat a.txt | paste - b.txt 这样的写法是合法的。
两个核心选项:-d和-s的实际用法
paste最常用的两个选项是-d和-s。-d用来指定分隔符,替代默认的Tab。比如想把两个字段用逗号拼起来生成CSV,直接 paste -d, a.txt b.txt 就行,比用awk拼要简洁得多。更妙的是,-d后面可以给多个分隔符,paste会按顺序循环使用它们。举个例子,paste -d',;' f1 f2 f3,输出格式就是第一列用逗号分隔、第二列用分号分隔,如果还有第四列,又回到用逗号。这个特性可以实现一些格式化输出的小技巧,但也正是很多人误会的来源,后面误区部分会细讲。
-s选项则是把每个文件的所有行水平串成一行,也就是行列反转式的合并。paste -s a.txt会把a.txt的三行变成一行,行与行之间默认用Tab隔开。配合-d可以改成任意分隔符,比如把多行的IP列表拼成逗号分隔的一行:
$ cat ips.txt 192.168.1.1 192.168.1.2 192.168.1.3 $ paste -sd, ips.txt 192.168.1.1,192.168.1.2,192.168.1.3
这个用法在批量操作时特别顺手,比如把文件列表拼成一行传给其他命令,或者把多行日志时间戳合成一条记录。对比一下awk的实现:awk '{printf "%s%s", sep, $0; sep=","} END{print ""}',功能一样但可读性差了不少。paste在这种简单拼接场景下几乎是最优解。
还有一个不太出名但好用的选项是--serial(等价于-s的另一种写法,GNU实现中-s就是serial的缩写形式),以及-d里的一些特殊字符转义,比如-d '\n'可以用换行符做分隔符,实现按列输出再转回按行的效果。这些组合让paste在行列变换上具备了和awk部分重叠的能力。
与cut命令配合:经典的拆分合并流水线
paste和cut是一对天然搭档。cut负责从一行里抽取某些列,paste负责把不同来源的列拼回去。一个典型场景:你有一个以冒号分隔的/etc/passwd风格文件,想重新调整字段顺序,比如把用户名和UID交换位置,可以先用cut分别取出两列,再用paste合并:
# 把第1列和第3列交换位置 cut -d: -f1 passwd.txt > tmp1 cut -d: -f3 passwd.txt > tmp2 paste -d: tmp2 tmp1 > new_passwd.txt
这个流水线虽然要生成临时文件,但逻辑清晰、不易出错。如果不想落盘,也可以用进程替换的写法:paste -d: <(cut -d: -f3 passwd.txt) <(cut -d: -f1 passwd.txt),在bash下同样有效,而且不产生中间文件。
另一个常见组合是处理日志对齐。假设有两个日志文件,一个记录时间戳,一个记录请求耗时,行数一致且顺序对应,用paste -d' '合并成一个文件就能直接喂给分析脚本。相比之下,用join命令做合并需要先排序且有共同的key字段,paste则完全不管内容,只按行号对齐,简单粗暴但胜在零成本。
从性能角度看,paste处理大文件也毫无压力,它是一个流式工具,逐行读取逐行输出,内存占用基本恒定。处理几个GB的日志时,paste的速度和cat相差无几,这点比某些需要全量载入内存的方案(比如用xargs或shell数组拼接)要可靠得多。
常见误区与踩坑提醒
第一个误区是分隔符的循环机制。-d参数给多个字符时,并不是所有列都用第一个字符分隔,而是按位置循环分配。有人写了 paste -d',' f1 f2 f3 以为全部用逗号分隔,结果第三个字段前变成了Tab,因为只给了逗号,循环到第三列时又回到了默认的Tab?其实不是,循环到第三列时用的是逗号本身(分隔符数量为1时就一直用逗号),真正出错的是类似 paste -d' |' 这种写法,本意是逗号加分隔说明,实际把空格和竖线当成了两个交替使用的分隔符。切记-d后面紧跟的每个字符都是一个分隔符,包括空格。
第二个误区是-s和多个文件组合的行为。paste -s f1 f2 不是把两个文件的所有行串成一整行,而是每个文件各自串成一行,输出两行。如果想要所有内容合并为一行,需要用 cat f1 f2 | paste -sd, 这样的写法。理解了-s的作用域是单个文件,就不会对输出结果感到困惑。
第三个误区是输出中的Tab干扰后续处理。paste默认用Tab分隔,而Tab在有些场景下会被下游工具当作普通空白处理,导致字段对不齐。稳妥的做法是始终显式指定-d,明确分隔符是什么,避免依赖默认值。另外,如果原文件内容本身含有Tab或分隔符字符,合并后的列边界就会混乱,这种情况建议先对内容做转义或换一个不太可能冲突的分隔符。
第四个坑是减号与stdin的组合顺序。paste - f1 会先读stdin再读f1,而 paste f1 - 则相反,stdin的位置决定了输出中它在第几列。在管道里写反了顺序,输出的列就颠倒了,排查起来还不直观。写脚本时建议用注释标明数据流向。
# stdin占第一列,f1内容占第二列 $ echo "hello" | paste - f1 hello 1 # f1内容占第一列,stdin占第二列 $ echo "hello" | paste f1 - 1 hello
最后提醒一点跨平台差异:macOS自带的BSD版paste和GNU版paste在选项上有细微差别,比如BSD版对-d多分隔符循环的支持基本一致,但某些长选项可能不存在。如果你写的脚本要跑在多种环境上,建议只用最基础的-d和-s,并在关键步骤做输出校验。掌握这些细节之后,paste就能成为你命令行工具箱里一个轻量又顺手的成员,该用的时候想得起来,用的时候不出意外。
Linux paste命令文本合并命令行工具修改时间:2026-09-06 19:27:21