了解何时使用tac命令代替cat,以及为何使用tac命令。
tac命令本质上是cat命令,但其目的是反向连接文件。 像cat一样,如果没有提供输出文件,它也具有方便的后备模式,可打印到标准输出(STDOUT),使其成为比lazy pager(像“less and more”)更常用的命令之一。该function因此命名。
cat命令经常被滥用,而tac通常被当作ddate或cowsay之类的玩笑命令。 愚人节的文章中经常详细介绍傻气的终端技巧。 所以当发现tac确实有合理的理由存在时,人们可能感到惊讶。
实际上tac是十分有效的命令。
tac的目的是什么?
tac手册在描述其自身功能方面表现不佳:
按照该语句写的内容,tac应该打印文件的最后一行,然后从第一行开始打印文件:
但这不是它的作用。 其信息页面表达得更为清晰:
例如:
忽略tac可以提供反向功能这一事实,其实它具有一些令人惊讶的实用且独特的选择。
Tac和分隔符
如信息页所示,该文件不必用行定界,这意味着tac对于CSV文件同样有效。 可以使用“--separator”或“-s”选项以及文件中使用的分隔符来定义文件的分隔符。
对于CSV文件,该字符可能是逗号(“,”),但是你可以定义任何字符。 然而,如果文件没有以分隔符结尾,那么你会得到意料之外的结果:
前两项之间没有分隔符。 文件的最终记录(在最终分隔符之后的字符串,在此情况下为逗号)本身并不后面跟逗号,因此tac会将其视为non-record。 要解决此问题,请使用“--before”或“-b”选项,它将分隔符放在每个记录之前:
分隔符不必是单个字符, 它也可以是正则表达式(regex)。
Tac和正则表达式
正则表达式的完整说明不在本文讨论范围之内,但是值得一提的是,扩展POSIX为环境变量所支持。 扩展的regex大大提高了正则表达式的可读性,为了简单起见,被本示例所采用。 假设有一个文件,其中包含所有用整数分隔的字符串:
你可以预见到字符串由整数分隔,但不能准确地预测这些整数是什么。 这正是正则表达式要解决的问题。
要在tac命令中使用regex,请在“--separator”定义之前使用“--regex”或“-r”选项。 另外,除非已经在你的环境中设置了它,否则必须激活REG_EXTENDED环境变量。 可以将此变量设置为除零以外的任何值以激活它,且可以通过所有常用方法进行操作:
- 导出你正在使用的Shell会话的变量。
- 在你的Shell配置文件(例如“〜/ .bashrc”)中设置环境变量。
- 将环境变量添加到tac命令(使用Bash,Zsh和类似命令)之前,如下例所示:
即使使用“--before”选项,regex选项也不能很好地处理未终止的记录。 如果该功能对你而言很重要,则可能需要调整源文件。
何时使用tac
这些简单而有用的解析选项使tac可作为不复杂,甚至极简的解析命令使用。对于那些不太值得编写AWK或Perl表达式的简单工作,tac可能是一个明智的解决方案。
很明显,tac命令是受限的,因为它除了逆转记录外不会以其他任何方式操作记录。但这有时是你唯一需要的列表操作。
例如,如果你打包分发软件,通常会列出安装所需的依赖项。根据收集此列表的方式,可以按照建立依赖关系所需的顺序(而不是安装它们的必要顺序)来获取它。
这种做法相对普遍,因为编译器错误首先触及到高级依赖项。也就是说,如果你的系统缺少libavcodec,则GCC会停止并发出警报;但也有其他例子,由于GCC尚未有机会针对libvorbis和libvpx探测你的系统,它无法告诉你这些依赖项也丢失了(并且在编译libavcodec之前,通常需要系统里已存在这些依赖项)。
因此,当你发现系统需要哪些库(libraries)来构建所需的库(等等)时,依赖性列表将以自顶向下的形式增长。在此过程结束时,tac可简单迅速地反转该列表。
另一个常见的棘手问题是日志文件。条目通常会附加到日志文件中,因此管理员可以使用tail查看最新错误。效果很好,但是有时候你想看到条目的“块”,却不知道需要走多远。通过tac命令传送到less或more的内容会将最新条目放在屏幕顶部。
最后,对于给定的部分,许多配置文件没有明确的终止标记。你可以查找awk和sed命令以设计一种方法来确定配置文件中的块何时结束,或者可以使用tac反转顺序。一旦解析器在该块中找到第一个相关条目,它就知道什么时候停止阅读,因为以前是页眉,现在是页脚。
Tac on
tac还有很多其他的重要用途,也许有很多原因使tac因太基本而无法成为解决问题的对策。 但是,你的系统可能已安装了该命令,因此,下次你若在工作流程中发现确实需要反向攻击的极端情况时,请记住此命令。