以下 to 命令有什么区别?
sort -u FILE
sort FILE | uniq
usingsort -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' 检查整条生产线。
同样,如果您对关键字段进行排序,则 sort 使用的唯一性测试不一定会再查看整行。在过去被那个 bug 咬过之后,这些天我在编写 Bash 脚本时倾向于使用“sort|uniq”。我宁愿有更高的 I/O 开销,也不愿冒这样的风险,即商店中的其他人在修改我的代码以添加额外的排序参数时不知道该特定陷阱。
sort -u
会稍微快一点,因为它不需要在两个命令之间传递输出
另请参阅我关于该主题的问题:calling uniq and sort in different order in shell
我在一些不支持'-u'选项的服务器上工作过。那里我们必须使用
sort xyz | uniq
没什么,它们会产生相同的结果