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


Answers:


119

sort | uniq以前存在sort -u,并且与更广泛的系统兼容,尽管几乎所有现代系统都支持-uPOSIX。这主要是回溯到sort -u不存在的时代(如果人们知道的方式继续起作用,人们就不会改变他们的方法,只看ifconfigvs. ip采用)。

可能合并了这两者,因为删除文件中的重复项需要排序(至少在标准情况下),这是排序的一种非常常见的用例。由于能够同时执行两个操作(并且由于它在uniq和之间不需要IPC的事实),因此在内部也更快sort。特别是如果文件很大,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数组,但这并不总是正确的)。


31
我倾向于使用,sort | uniq因为实际上是十分之九uniq -c
Plutor

5
请注意,它sort -u是1979年第7版UNIX的一部分。sort不支持的版本-u确实是过时的-或在撰写时未关注POSIX法定标准之前的实际标准。另请参见2010
Jonathan Leffler 2015年

3
由于+1 ip。现在是2016年,这个职位是2013年,但是我ip现在只了解命令。

4
+1表示“ 9次实际上是10个管道,实际上是管道连接到uniq -c”(也可能再次管道连接到sort -nr | head)。sort | uniq当我发现Vim有:sort u命令时,我想知道什么与Vim中的命令等效。TIL也sort -u存在。
卓卓玮

请注意,使用sort -n | uniqvs.会有所不同sort -n -u。例如,尾部和前导空格将被sort -n -u前者视为重复,但前者则不会!echo -e 'test \n test' | sort -n -u返回test,但echo -e 'test \n test' | sort -n | uniq返回两行。
mxmlnkn

46

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


3
+0.49是一个有用的答案,但我会这样说:“ sort -u无法将的输出传递uniq给使用后者的一些有用选项,例如跳过用于比较的字段和计算重复次数。”
l0b0

15
+1抵消了反对者的反对,因为“没有办法直接从排序中做到这一点” 确实回答了这个问题……
Izkata

42

使用POSIX兼容的sorts和uniqs(uniq在这方面,GNU 当前不兼容),区别在于sort使用语言环境的整理算法比较字符串(通常将strcoll()用于比较字符串),同时uniq检查字节值同一性(通常使用strcmp()) 。

至少有两个原因很重要。

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

    对于sort -u,①与②相同,而0123与sort相同,因此sort -u将仅保留其中的一个,而对于uniq(不是uniq使用strcoll()(除外-i)的GNU ),①与②不同,并且0123与different不同,因此uniq将考虑全部4个独特。

  • strcoll只能比较有效字符的字符串(当输入包含不构成有效字符的字节序列时,行为未按POSIX定义),strcmp()而不关心字符,因为它仅进行字节对字节的比较。因此,这是另一个原因,sort -u如果其中某些行不能形成有效的文本,则可能无法为您提供所有的行。sort|uniq,尽管仍未在非文本输入中指定,但实际上由于这个原因,您更有可能给您提供独特的提示。

除了这些细微差别外,到目前为止尚未注意到的一件事是按uniq词法比较整行,而sort-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

9

我更喜欢使用,sort | uniq因为当我尝试使用-u(消除重复项)选项来删除涉及大小写混合的重复项时,要理解结果并不容易。

注意:在运行下面的示例之前,您需要通过执行以下操作来模拟标准的C整理序列:

LC_ALL=C
export LC_ALL

例如,如果我要对文件进行排序并删除重复项,同时要使字符串的不同情况保持不同。

$ cat short      #file to sort
Pear
Pear
apple
pear
Apple

$ sort short     #normal sort (in normal C collating sequence)
Apple            #the lower case words are at the end
Pear
Pear
apple
pear

$ sort -f short  #correctly sorts ignoring the C collating order
Apple            #but duplicates are still there
apple
Pear
Pear
pear

$ sort -fu short #By adding the -u option to remove duplicates it is 
apple            #difficult to ascertain the logic that sort uses to remove
Pear             #duplicates(i.e., why did it remove pear instead of Pear?)

通过不使用-u删除重复项的选项来解决此混淆。使用uniq更可预测。下面首先对大小写进行排序并忽略该大小写,然后将其传递uniq以删除重复项。

$ sort -f short | uniq
Apple
apple
Pear
pear

2
-u选项sort输出均等运行的一个(请参见手册页)。因此sort -fu,每个不区分大小写的唯一行都将首先出现。sort用于删除重复项的逻辑是可以预测的。
pallxk 2015年

3

我今天发现的另一个区别是,当基于分隔符进行排序时,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

这是在StéphaneChazelas的答复中提到的,但我喜欢您的例子,所以+1
roaima

感谢您指出@roaima,答案不太清楚
Stefanos Chrs
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.