“sort -u”和“sort | uniq”有什么区别?

“sort -u”和“sort | uniq”有什么区别?

每当我看到有人需要获取已排序的唯一列表时,他们总是通过管道传输到sort | uniq。我从未见过有人使用 的例子sort -u。为什么不呢?有什么区别,为什么使用 uniq 比使用 unique 标志进行排序更好?

答案1

sort | uniq以前就存在sort -u,并且与更广泛的系统兼容,尽管几乎所有现代系统都支持-u——它是 POSIX。这主要是对不存在的日子的倒退sort -u(如果人们知道的方式继续有效,那么人们不会倾向于改变他们的方法,只需看看与采用ifconfig相比ip)。

两者很可能合并,因为删除文件中的重复项需要排序(至少在标准情况下),并且是排序的极其常见的用例。由于能够同时执行这两个操作(并且由于它不需要 IPC(进程间通信) 之间uniqsort。特别是如果文件很大,sort -u可能会使用更少的中间文件来对数据进行排序。

在我的系统上,我一直得到这样的结果:

$ dd if=/dev/urandom of=/dev/shm/file bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 8.95208 s, 11.7 MB/s
$ time sort -u /dev/shm/file >/dev/null

real        0m0.500s
user        0m0.767s
sys         0m0.167s
$ time sort /dev/shm/file | uniq >/dev/null

real        0m0.772s
user        0m1.137s
sys         0m0.273s

它也不会屏蔽 的返回码sort,这可能很重要(在现代 shell 中,有多种方法可以获取它,例如bash$PIPESTATUS数组,但这并不总是正确的)。

答案2

对于 POSIX 兼容的sorts 和uniqs(GNUuniq目前在这方面不兼容),有区别其中sort使用区域设置的整理算法来比较字符串(通常用于strcoll()比较字符串),同时uniq检查字节值标识(通常使用strcmp())。

这很重要,至少有两个原因。

  • 在某些语言环境中,尤其是在 GNU 系统上,有不同的字符可以进行相同的排序。例如,在 GNU 系统上的 en_US.UTF-8 语言环境中,所有①②③④⑤⑥⑦⑧⑨⑩...字符²和许多其他字符的排序相同,因为它们的排序顺序未定义。 0123456789 阿拉伯数字的排序与其相同东阿拉伯印度语对应物(٠١٢٣٤٥٦٧٨٩)。

    对于sort -u,① 与 ② 排序相同,0123 与 ٠١٢٣ 排序相同,因此sort -u仅保留其中一个,而对于(不是使用(除了)的uniqGNU ),① 与 ② 不同,0123 与 ٠١٢٣ 不同,因此会考虑所有4独特。uniqstrcoll()-funiq

  • strcoll只能比较有效字符的字符串(当输入具有不形成有效字符的字节序列时,根据 POSIX 未定义行为),而不strcmp()关心字符,因为它只进行字节到字节的比较。因此sort -u,如果其中一些行未形成有效文本,这就是为什么可能无法为您提供所有唯一行的另一个原因。 sort|uniq,虽然在非文本输入上仍未指定,但实际上更有可能因此为您提供独特的行。

除了这些微妙之处之外,到目前为止还没有注意到的一件事是,从uniq词法上比较整行,而sorts-u根据命令行上给出的排序规范进行比较。

$ printf '%s\n' 'a b' 'a c' | sort -uk 1,1
a b
$ printf '%s\n' 'a b' 'a c' | sort -k 1,1 | uniq
a b
a c

$ printf '%s\n' 0 -0 +0 00 '' | sort -n | uniq
0
-0
+0
00

$ printf '%s\n' 0 -0 +0 00 '' | sort -nu
0

1 POSIX 规范的早期版本通过将LC_COLLATE变量列为影响 的变量而引起混乱uniq,该变量在 2018 年版本中被删除,并且在上述讨论之后澄清了行为。看相应的奥斯汀组错误

²2019年编辑。这些问题已经得到解决,但是自 GNU libc 版本 2.30 起,超过 95% 的 Unicode 代码点仍然具有未定义的顺序。你可以测试

答案3

一个区别是它uniq有许多有用的附加选项,例如跳过字段进行比较和计算值的重复次数。sort-u标志仅实现未修饰命令的功能uniq

答案4

我今天发现的另一个区别是,当基于分隔符进行排序时,sort -u仅在您排序的列上应用唯一标志。

$ cat input.csv
3,World,1
1,Hello,1
2,Hello,1

$ cat input.csv | sort -t',' -k2 -u
1,Hello,1
3,World,1

$ cat input.csv | sort -t',' -k2 | uniq
1,Hello,1
2,Hello,1
3,World,1

相关内容