以下两个命令有什么区别?
sort -u FILE
sort FILE | uniq
使用sort -u
比使用sort | uniq
的I/O要少,但最终结果相同。特别是如果文件足够大,sort
需要创建中间文件,那么sort -u
可能会使用稍微较少或稍微较小的中间文件,因为在排序每个集合时可以消除重复项。如果数据高度重复,则可能有益;如果实际上很少重复,那么这不会有太大的区别(与管道的一级性能效果相比,肯定是二级性能效果)。
请注意,有时候使用管道是适当的。例如:
sort FILE | uniq -c | sort -n
这将按照文件中每行出现次数的顺序对文件进行排序,重复出现最多的行将出现在最后。(我不会感到惊讶,如果发现这种组合,在Unix或POSIX上是习惯用法,可以通过GNU sort命令压缩成一个复杂的排序命令。)
有时候不使用管道是很重要的。例如:
sort -u -o FILE FILE
这会“原地”排序文件;也就是说,输出文件由-o FILE
指定,并且此操作是安全的(在写入输出之前,先读取该文件)。
sort | uniq -c | sort -n
的所有操作,我也没有找到其他有效的工具来实现它。看起来编写这样一个工具是值得的。 - mc0e有一点小区别:返回值。
问题在于,除非设置了shopt -o pipefail
,否则管道命令的返回值将是最后一个命令的返回值。而uniq
总是返回零(成功)。尝试检查退出代码,你会看到类似这样的内容(此处未设置pipefail
):
pavel@lonely ~ $ sort -u file_that_doesnt_exist ; echo $?
sort: open failed: file_that_doesnt_exist: No such file or directory
2
pavel@lonely ~ $ sort file_that_doesnt_exist | uniq ; echo $?
sort: open failed: file_that_doesnt_exist: No such file or directory
0
除此之外,这些命令是等效的。
注意!虽然"sort -u"和"sort | uniq"是等效的,但是任何对sort的附加选项都可能破坏它们之间的等价性。这里有一个来自coreutils手册的例子:
例如,“sort -n -u”只检查初始数字字符串的值以检查唯一性,而“sort -n | uniq”则检查整行。
同样地,如果你按关键字段进行排序,sort使用的唯一性测试就不再必须检查整行了。在过去被这个问题困扰过后,现在我倾向于在编写Bash脚本时使用"sort | uniq"。我宁愿有更高的I/O开销,也不想冒着别人不知道添加额外的sort参数会导致的问题风险。
我曾在一些服务器上工作,其中sort命令不支持“-u”选项。在这种情况下,我们需要使用
sort xyz | uniq
sort
支持-u
,这是UNIX的第一个广泛使用的版本,因此所有其他版本(System III、System V、BSD等)都倾向于遵循它,所以我会非常惊讶地发现一个类Unix系统不支持-u
。 - Jonathan Leffler没有区别,它们会产生相同的结果
-u
选项在UNIX第七版的sort
命令中(大约是1979年)就已经存在了,因此所涉及的古代历史确实非常久远。 - Jonathan Leffler