Как работает 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 значительно

Другие вопросы по тегам