跑步
printf "lol\nlol\nfoo\n\n\n\n\nbar\nlol\nlol\nfoo\nlol\nfoo" | uniq --unique
印刷
foo
bar
foo
lol
foo
为什么foo
打印了三遍?不应该uniq --unique
删除它们吗?
另外,值得注意的是,似乎所有重复项lol
都被删除了。为什么是哈哈重复项被删除,但没有富重复?
答案1
uniq
man uniq
如果您希望删除输入,则需要对输入进行排序(来自)全部重复行:
描述
从 INPUT(或标准输入)中过滤相邻的匹配行,写入 OUTPUT(或标准输出)。
正如你在上面看到的,它只过滤邻近的匹配线。这就是lol
删除 s 的原因。因此,在传递到之前对数据进行排序uniq
:
$ printf "lol\nlol\nfoo\n\n\n\n\nbar\nlol\nlol\nfoo\nlol\nfoo" | sort | uniq
bar
foo
lol
或者,使用 GNU sort
,跳过uniq
:
$ printf "lol\nlol\nfoo\n\n\n\n\nbar\nlol\nlol\nfoo\nlol\nfoo" | sort --unique
bar
foo
lol
最后,如果您想完全删除多次出现的行(而不是保留一份副本,默认行为),请使用uniq -u
或--unique
如您的问题中所示:
$ printf "lol\nlol\nfoo\n\n\n\n\nbar\nlol\nlol\nfoo\nlol\nfoo" | sort | uniq -u
bar
然而,在所有情况下,排序都是必要的。
答案2
您想问为什么foo
仍在列表中吗?uniq
只删除相邻的重复行,将相邻的重复行“挤压”成单行。使用-u
(或--unique
使用 GNU uniq
),它还会删除具有相邻重复行的行。
在您的示例中,这三行中没有任何一行foo
与任何其他行相邻foo
。这就是它们被输出的原因。
被删除的行lol
被删除是因为它们与另一行相邻,内容为lol
。最后lol
一行在这个意义上没有重复,因此被保留。