Как работает uniq? [дубликат]

Не путайте этот вопрос с дублированием "в чем разница ч / б 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

Конвейер вывода для сортировки, а затем в 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
задан 31 October 2016 в 22:17

1 ответ

Это не случайное поведение. От man uniq:

Примечание: 'uniq' не обнаруживает повторенные строки, если они не смежны. Можно хотеть отсортировать вход сначала или использование 'вид-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, если строки не являются тем же, Ложь, если они - то же. Причина того действительно состоит в том, что, если бы необходимо было выдержать сравнение со всеми строками, Вам, вероятно, был бы нужен большой объем памяти, если существует большое количество строк. Это не практично, и замедлилось бы uniq значительно

2
ответ дан 7 December 2019 в 13:40

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

Похожие вопросы: