Как работает Uniq?
Не путайте этот вопрос с тем, чтобы он был дубликатом "в чем разница между ч / б, сортировать -u и сортировать | 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
Передача результатов в сортировку, а затем в 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" не обнаруживает повторяющиеся строки, если они не являются смежными. Вы можете сначала отсортировать ввод или использовать sort -u без uniq. Кроме того, сравнения соответствуют правилам, указанным в 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
значительно