以下两个命令有什么区别?
sort -u FILE
sort FILE | uniq
使用
sort -u
的 I/O 量比 sort | uniq
少,但最终结果是相同的。特别是,如果文件足够大,sort
必须创建中间文件,那么 sort -u
很有可能会使用稍少或稍小的中间文件,因为它可以在对每组进行排序时消除重复项。如果数据高度重复,这可能是有益的;如果事实上重复很少,则不会有太大区别(与管道的一阶效果相比,绝对是二阶性能效果)。
请注意有时配管是合适的。例如:
sort FILE | uniq -c | sort -n
这会按照文件中每行出现的次数对文件进行排序,重复次数最多的行出现在最后。 (如果我发现这种 Unix 或 POSIX 惯用的组合可以通过 GNU sort 压缩成一个复杂的“排序”命令,我不会感到惊讶。)
有时不使用管道很重要。例如:
sort -u -o FILE FILE
这会“就地”对文件进行排序;也就是说,输出文件由
-o FILE
指定,并且此操作保证安全(在覆盖输出之前先读取文件)。
有一个细微的差别:返回代码。
问题是,除非设置了
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”确实是等效的,但任何附加的排序选项都可能会破坏等效性。这是 coreutils 手册中的一个示例:
例如,“sort -n -u”在检查唯一性时仅检查初始数字字符串的值,而“sort -n |”则仅检查初始数字字符串的值。 uniq' 检查整条生产线。
同样,如果您对关键字段进行排序,则排序使用的唯一性测试不一定会再查看整行。在过去被这个 bug 困扰之后,现在我在编写 Bash 脚本时倾向于使用“sort|uniq”。我宁愿有更高的 I/O 开销,也不愿冒着商店中的其他人在修改我的代码以添加其他排序参数时不知道该特定陷阱的风险。
sort -u
会稍微快一些,因为它不需要在两个命令之间通过管道传输输出
另请参阅我关于该主题的问题:calling uniq and sort in different order in shell
我曾在一些排序不支持“-u”选项的服务器上工作过。在那里我们必须使用
sort xyz | uniq
没什么,他们会产生相同的结果