什么是 tac 命令?
tac 命令是 cat 命令的“反向”版本,它的名字就是 cat 的倒写。

cat(Concatenate): 从上到下按行显示文件内容。tac: 从下到上按行显示文件内容,即逆序输出文件的每一行。
cat 是 "catenate"(连接)的缩写,而 tac 的名字则是一个巧妙的双关语,暗示了它与 cat 的相反行为。
基本语法
tac [选项]... [文件]...
[选项]...: 可选的命令行参数,用于改变tac的行为。[文件]...: 一个或多个要处理的文件,如果没有指定文件,或者文件名为 ,则从标准输入读取。
常用选项
tac 的选项比 cat 少很多,因为它主要用于简单的逆序输出。
| 选项 | 全称 | 描述 |
|---|---|---|
-b, --before |
before | 在分隔符之前而不是之后附加内容,主要用于处理多字节字符的分隔符。 |
-r, --regex |
regex | 将分隔符解释为正则表达式。 |
--help |
help | 显示帮助信息并退出。 |
--version |
version | 显示版本信息并退出。 |
重要提示: tac 默认使用换行符 \n 作为行分隔符,这意味着它只是将行的顺序颠倒,而不会颠倒行内的字符顺序。
使用示例
我们首先创建一个示例文件 example.txt如下:

$ cat > example.txt Line 1: This is the first line. Line 2: This is the second line. Line 3: This is the third line. Line 4: This is the fourth line. ^C (按 Ctrl+C 结束输入)
示例 1:基本用法 - 逆序显示文件内容
这是 tac 最核心的功能,它会从文件的最后一行开始,向上打印到第一行。
$ tac example.txt Line 4: This is the fourth line. Line 3: This is the third line. Line 2: This is the second line. Line 1: This is the first line.
示例 2:处理多个文件
如果提供多个文件,tac 会按顺序逆序处理每个文件。
首先创建第二个文件 another.txt:
$ echo "File A, Line 1" > another.txt $ echo "File A, Line 2" >> another.txt
现在使用 tac 处理两个文件:

$ tac example.txt another.txt File A, Line 2 File A, Line 1 Line 4: This is the fourth line. Line 3: This is the third line. Line 2: This is the second line. Line 1: This is the first line.
可以看到,another.txt 的内容被逆序输出,然后才是 example.txt 的逆序内容。
示例 3:从标准输入读取
tac 可以像 cat 一样,通过管道接收其他命令的输出。
$ cat example.txt | tac Line 4: This is the fourth line. Line 3: This is the third line. Line 2: This is the second line. Line 1: This is the first line.
这与直接在文件上使用 tac 效果相同。
示例 4:使用 -r 选项(正则表达式分隔符)
tac 默认只识别换行符 \n 作为分隔符,假设你有一个文件,其中用 作为分隔符,但你希望以 为单位进行逆序。
创建一个新文件 separator.txt:
$ cat > separator.txt Section 1 --- Section 2 --- Section 3
不使用 -r 选项:
tac 会把每一行都看作一个独立的行,然后逆序它们。
$ tac separator.txt Section 3 --- Section 2 --- Section 1
这显然不是我们想要的结果。
使用 -r 选项:
我们将分隔符 定义为一个正则表达式。
$ tac -r -s '---' separator.txt Section 3 --- Section 2 --- Section 1
等等,看起来结果一样? 让我们再仔细看看,哦,tac 在处理时,会先将文件按 分割成几个“块”,然后逆序这些“块”,在这个简单的例子中,顺序看起来没变,因为每个块只有一行,让我们换一个更复杂的例子:
$ cat > complex.txt Header --- Part A, Line 1 Part A, Line 2 --- Part B, Line 1 Part B, Line 2 --- Footer
现在使用 -r 选项:
$ tac -r -s '---' complex.txt Footer --- Part B, Line 1 Part B, Line 2 --- Part A, Line 1 Part A, Line 2 --- Header
这次结果就非常清晰了:整个文件被 分成了几个大块,然后这些大块的顺序被完全颠倒了。
tac vs. rev
初学者常常会混淆 tac 和 rev 命令,因为它们都和“反向”有关。
| 命令 | 功能 | 示例输入 hello world |
|---|---|---|
tac |
逆序行 (Reverse lines) | worldhello |
rev |
逆序字符 (Reverse characters) | dlrow olleh |
tac是按行倒着看。rev是按字符倒着看。
tac 的局限性
tac 的实现方式决定了它有一个重要的性能限制:它需要将整个文件读入内存才能进行逆序操作,这是因为文件存储在磁盘上是顺序的,要逆序输出,tac 必须先读取所有内容,找到行尾,然后反向构建输出。
对于非常大的文件(例如几十GB的日志文件),使用 tac 可能会导致内存耗尽(OOM)或系统变得非常缓慢。
替代方案:处理大文件
如果你需要逆序查看一个非常大的文件,tac 就不是最佳选择了,这时可以使用 tail 和 awk 的组合。
方法:使用 tail 和 awk
这个组合的原理是:tail 可以从文件末尾开始读取,awk 可以逐行处理。
# 语法
tail -n +1 文件名 | awk '{a[i++]=$0} END {for (j=i-1; j>=0; j--) print a[j]}'
# 示例
tail -n +1 example.txt | awk '{a[i++]=$0} END {for (j=i-1; j>=0; j--) print a[j]}'
命令解析:
tail -n +1 example.txt:tail从文件的第一行开始读取到最后一行,并输出到标准输出,这相当于cat,但在这里是为了与awk管道连接。awk '{a[i++]=$0}':awk逐行读取输入。$0代表整行,a[i++]=$0将每一行存入数组a,索引i从 0 开始递增。END {for (j=i-1; j>=0; j--) print a[j]}:awk处理完所有行后(END块),执行循环,循环从数组的最后一个索引 (i-1) 开始,反向遍历到 0,并打印出对应的行,从而实现了逆序。
这种方法比 tac 更节省内存,因为它不需要一次性将整个文件加载到内存中。
| 特性 | tac |
tail + awk |
|---|---|---|
| 功能 | 逆序输出文件的行 | 逆序输出文件的行 |
| 易用性 | 非常简单,一个命令即可 | 较复杂,需要组合命令 |
| 内存消耗 | 高,需要加载整个文件 | 低,逐行处理 |
| 适用场景 | 小文件,快速查看 | 大文件,避免内存问题 |
何时使用 tac?
当你需要快速逆序查看一个小到中等大小的文件时,tac 是最直接、最方便的选择。
何时使用替代方案?
当你处理的文件非常大,可能会耗尽系统内存时,应该使用 tail 和 awk 的组合,或者其他更专业的工具(如 perl 脚本)。
