![uniq 如何工作?](https://linux22.com/image/888174/uniq%20%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%EF%BC%9F.png)
不要混淆这个问题与“sort -u 和 sort | uniq 之间有什么区别”的重复
这本质上是一个字数统计程序
以下命令引起的混淆是提出此问题的原因:
root@sanctum:~/datascience# cat data
this is a file that is supposed to be a file
这给出了错误的输出:
root@sanctum:~/datascience# cat data | sed 's/ /\n/g' | uniq -c
1 this
1 is
1 a
1 file
1 that
1 is
1 supposed
1 to
1 be
1 a
1 file
将输出通过管道传输到 sort,然后再传输到 uniq,可以得到完美的答案-
root@sanctum:~/datascience# cat data | sed 's/ /\n/g' | sort |uniq -c
2 a
1 be
2 file
2 is
1 supposed
1 that
1 this
1 to
通过管道输出时仅进行排序:
root@sanctum:~/datascience# cat data | sed 's/ /\n/g' | sort
a
a
be
file
file
is
is
supposed
that
this
to
一行出现的行数如何影响文件中出现的次数?我不知道该如何表达,但你明白我的意思
基本上为什么不能cat data | sed 's/ /\n/g' | uniq -c
给出所需的结果?
答案1
这不是随机行为。从man uniq
:
笔记:除非重复行相邻,否则“uniq”不会检测重复行。您可能希望先对输入进行排序,或者使用不带“uniq”的“sort -u”。此外,比较遵循“LC_COLLATE”指定的规则。
本质上,uniq
默认情况下仅适用于已排序输入。换句话说,这是设计使然。
但你的主要问题是:
一行出现的行数如何影响文件中出现的次数
while (!feof (stdin))
{
char *thisfield;
size_t thislen;
if (readlinebuffer_delim (thisline, stdin, delimiter) == 0)
break;
thisfield = find_field (thisline);
thislen = thisline->length - 1 - (thisfield - thisline->buffer);
if (prevline->length == 0
|| different (thisfield, prevfield, thislen, prevlen))
{
fwrite (thisline->buffer, sizeof (char),
thisline->length, stdout);
SWAP_LINES (prevline, thisline);
prevfield = thisfield;
prevlen = thislen;
}
}
这里的关键是读取文件逐行并且只能在函数中对当前行和前一行进行比较,different()
如果行不相同,则返回 True,如果相同,则返回 False。这样做的原因实际上是,如果你要比较全部行,如果行数很多,你可能需要大量内存。这不切实际,而且会大大降低uniq
速度