uniq为何还不够独特,以至于也只有uniq --unique?


35

这是来自pastebin的随机文件上的命令:

wget -qO - http://pastebin.com/0cSPs9LR | wc -l
350
wget -qO - http://pastebin.com/0cSPs9LR | sort -u | wc -l
287
wget -qO - http://pastebin.com/0cSPs9LR | sort | uniq | wc -l
287
wget -qO - http://pastebin.com/0cSPs9LR | sort | uniq -u | wc -l
258

手册页不清楚该-u标志在做什么。有什么建议吗?


4
尝试排序| uniq -d | wc -l,您可能会发现差异。:)
stoeff

Answers:


42

简洁版本:

  • uniq,不带-u,将使输出的每一行都是唯一的。
  • uniq -u仅打印输入中的每一行。

版本稍长:

uniq仅用于处理行重复的文件,并且仅当这些行在输入中连续出现时。因此,就其目的而言,唯一行是不会立即重复的行。

uniq短期记忆非常有限;除非它紧接在前一行,否则它将永远不会记住该行是否在输入的前面出现,这就是为什么uniq经常与之配对的原因sort。)

如果遇到一排重复的行,uniq则不带-uarg 的行将打印该行的一个副本。(这使输出的每一行都是唯一的)。

使用该-u参数,它将打印该行的份副本-重复的运行只会从输出中省略。


1
我真的希望有一个不需要排序的选项。但这需要将整个文件保留在内存中(如果源是普通文件,则需要使用哈希和偏移量进行大量簿记)
Random832

3
@ Random832:这将需要确定要保留哪些重复对象(首先,最后是其他东西,可配置),并且该决定将全局影响算法。麻烦
史蒂夫·杰索普

1
@ Random832:如果只是要键入的字符数,则可以使用sort -u代替sort | uniq
奥利弗2015年

@oliver我偶尔想要一种能够保留任何行的第一个实例而无需重新排列它们的功能,并编写了脚本来做到这一点。
Random832

1
@hvd:如果您的版本进行uniq规范化和归类,则可以。但是即使如此,这仍然只是本地的考虑因素-您知道该行将出现在已排序的输出中的位置,并且只需要选择保留几条相邻行中的哪一行即可。如果未对输入进行排序,那么该决定会影响uniqifying的整个操作,例如,如果您要保留最后一个重复项,那么您必须先阅读输入的最后一行,然后才能输出任何内容...
Steve Jessop 2015年

53

uniq-u跳过任何重复的行。从而:

$ printf "%s\n" 1 1 2 3 | uniq
1
2
3
$ printf "%s\n" 1 1 2 3 | uniq -u
2
3

通常,uniq最多打印一次行(假设已排序的输入)。此选项实际上打印真正唯一的行(不再出现)。


11
也就是说,uniq可以称为distinct,因为它打印所有不同的行,而uniq -u打印所有唯一的行。
史蒂夫·杰索普

在某些地区,GNU 并不是真正独特的uniq
cuonglm 2015年

我一定已经读过几次接受的答案,但是并没有陷入。您的示例和它后面的段落很清楚(然后回过头来重新阅读接受的答案,我也明白了):)
Madivad

18

uniq POSIX规范清楚地描述了它:

-u
    Suppress the writing of lines that are repeated in the input.

-u选项使uniq不打印重复的行。

大多数uniq实现使用字节比较,而GNU uniq使用排序规则来过滤重复的行。因此,在某些语言环境中可能会产生错误的结果,例如在en_US.UTF-8语言环境中:

$ printf '%b\n' '\U2460' '\U2461' | uniq
①

-u没有给您任何内容:

$ printf '%b\n' '\U2460' '\U2461' | uniq -u
<blank>

因此,您应该将locale设置为C以获得字节比较:

$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=C uniq
①
②

3
请注意,这里的错误不是那么多uniq(尽管POSIX的意图显然是它应该sort -u像②中那样对那些错误地进行了①排序的语言环境进行字节比较,而不是像中的strcoll()比较)。至少GNU uniq与一致sort -u
斯特凡Chazelas

@StéphaneChazelas-规格在哪里显而易见?
mikeserv

关于uniq做memcmp / strcmp而不是strcoll,这对我来说不是很明显,但是对Geoff来说。关于①与②排序相同的GNU语言环境,这显然是一个错误,因为没有理由对它们进行排序。POSIX允许这样做,但是会有一些变化
斯特凡Chazelas

8

正常:

echo "a b a b c c c" | tr ' ' '\n'
a
b
a
b
c
c
c

uniq:后续没有重复的两行

echo "a b a b c c c" | tr ' ' '\n' | uniq
a
b
a
b
c

已排序

echo "a b a b c c c" | tr ' ' '\n' | sort
a
a
b
b
c
c
c

-u排序:没有两行重复

echo "a b a b c c c" | tr ' ' '\n' | sort -u
a
b
c

排序/唯一性:所有不同

echo "a b a b c c c" | tr ' ' '\n' | sort | uniq
a
b
c

计算不同的事件

echo "a b a b c c c" | tr ' ' '\n' | sort | uniq -c
2 a
2 b
3 c

仅不重复的行(不首先排序)

echo "a b a b c c c" | tr ' ' '\n' | uniq -u
a
b
a
b

仅不重复的行(排序后)

echo "a b a b c c c Z" | tr ' ' '\n' | sort | uniq -u
Z

uniq -d:仅打印重复的行,每组一行

echo "a b a b c c c" | tr ' ' '\n' | uniq -d
c

..算了

echo "a b a b c c c" | tr ' ' '\n' | uniq -dc
3 c

漂亮的例子:)
Madivad
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.