Наши партнеры

UnixForum






Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

На главную -> MyLDP -> Тематический каталог -> Работа в консоли Linux

HuMan: uniq

Автор: Алексей Дмитриев
Дата: 5 февраля 2009

Команда uniq без опций

Если в тексте следует подряд несколько одинаковых строк, то команда uniq уменьшит их количество до одной.

$ echo -e 1234\\n2345\\n3456\\n1111\\n1111\\n1111 | uniq

1234
2345
3456
1111

Расшифрую этот пример. Команду echo, при помощи опции -e можно заставить печатать не в строчку, как обычно, а в несколько строк. Для этого нужно в конце каждой будущей строки поставить знак новой строки \n, а чтобы "экранировать" обратный слэш (\), который сам по себе тоже является знаком, нужно этот обратный слэш удвоить: \\, и получится \\n. Например, напечатаем в две строки какой-нибудь стишок, например:

$ echo -e Глупый пингвин\\nРобко прячет

Глупый пингвин
Робко прячет

(Кто не знает, сообщу по секрету, что великий пролетарский писатель Максим Горький в слове пингвин ставил ударение на первом слоге - пИнгвин). Пробел между знаком новой строки и первым словом следующей строки не ставится, иначе получится "лесенка":

$ echo -e Глупый пингвин\\n Робко прячет

Глупый пингвин
 Робко прячет

как в стихах другого великого пролетарского поэта Маяковского:

$ echo -e Били копыта\\n пели как-будто...

Били копыта
 пели как-будто...

Но довольно поэзии; вернемся к нашему числовому примеру:

$ echo -e 1234\\n2345\\n3456\\n1111\\n1111\\n1111 | uniq

1234
2345
3456
1111

Итак, в первой части этого программного канала команда echo -e, которая выводит на стандартный вывод столбик чисел. Вывод этот канализируется на ввод команды uniq, которая уменьшает количество одинаковых строк (1111) до одной.

Тут нужно уточнить очень интересную вещь: команда uniq сравнивает только рядом расположенные строчки, и если составить столбик цифр в другом порядке, скажем:

$ echo -e 1234\\n1111\\n2345\\n1111\\n3456\\n1111 | uniq

1234
1111
2345
1111
3456
1111

то никакого уменьшения числа повторов не произойдет. Становится понятным, что команда uniq любит уже отсортированные тексты, где все одинаковые строчки собраны вместе. Такой сортировкой славится команда sort, вот и добавим ее в наш программный канал:

$ echo -e 1234\\n1111\\n2345\\n1111\\n3456\\n1111 | sort | uniq

1111
1234
2345
3456

Команда sort сортирует, команда uniq убирает повторы, кажется все прекрасно, если бы не одно "но" - у программы sort есть опция -u, которая справляется с этой задачей не хуже:

$ echo -e 1234\\n1111\\n2345\\n1111\\n3456\\n1111 | sort -u

1111
1234
2345
3456

Получается, что команда uniq как бы и не нужна...

Не спешите с выводами, у команды uniq есть еще несколько опций, которых нет у команды sort.

Опция -c

--count

Сообщит, сколько было одинаковых строк до их урезания:

$ echo -e кот\\nконь\\nсобака\\nкрыса\\nкрыса | uniq -c
      
      1 кот
      1 конь
      1 собака
      2 крыса

Опция -d

--repeated

Эта опция, наоборот, выведет лишь ту строку, которая повторялась в тексте:

$ echo -e кот\\nконь\\nсобака\\nкрыса\\nкрыса | uniq -d

крыса

Можно узнать и сколько раз эта строка повторялась:

$ echo -e кот\\nконь\\nсобака\\nкрыса\\nкрыса | uniq -dc
      
       2 крыса

Опция -D (расширение GNU)

--all-repeated

Выведет все повторяющиеся строки, не уменьшая их числа:

$ echo -e кот\\nконь\\nсобака\\nкрыса\\nкрыса | uniq -D

крыса
крыса

На первый взгляд, это не слишком полезно, но в сочетании с некоторыми другими опциями вполне имеет смысл.

Опция -u

--unique

Выводит только уникальные строки:

$ echo -e кот\\nконь\\nсобака\\nкрыса\\nкрыса | uniq -u

кот
конь
собака

Опция -f

--skip-fields=ЧИСЛО

-ЧИСЛО

Эта опция пропустит указанное ЧИСЛО "слов", прежде чем начать искать повторы. Тут следует пояснить, что "словом" команда uniq считает любую непрерывную последовательность символов, отделенную от других символов знаками пробела, либо табуляции (таковых знаков может быть один или больше).

$ echo -e Иванов Сергей\\nИванов Михаил\\nИванов Иван\\nИванов Иван\\nИванов Константин | uniq -f 1

Иванов Сергей
Иванов Михаил
Иванов Иван
Иванов Константин

В этом примере мы пропустили заведомо одинаковую фамилию, чтобы "отцедить" двойников Иванов. (Правда, безо всяких опций сработало бы не хуже, но в каких-то случаях, скорее всего, эта опция полезна).

Можно скомбинировать эту опцию с другими, слегка изменив синтаксис:

$ echo -e Иванов Сергей\\nИванов Михаил\\nИванов Иван\\nИванов Иван\\nИванов Константин | uniq -f1 -c
      1 Иванов Сергей
      1 Иванов Михаил
      2 Иванов Иван
      1 Иванов Константин

В таком виде она имеет определенный смысл.

Можно было задать эту опцию проще: uniq -1.

Опция -s

--skip-chars=ЧИСЛО

+ЧИСЛО

Эта опция пропустит необходимое ЧИСЛО символов, прежде начала поиска повторов.

$ echo -e пивовар\\nмыловар\\nсыровар | uniq -s 4

пивовар

Эту опцию можно комбинировать с другими, если записать без пробела между -s и ЧИСЛОМ:

$ echo -e 111222\\n111333\\n111444 | uniq -s3 -c
      
      1 111222
      1 111333
      1 111444

Можно также ставить просто: uniq +3.

Опция -w

--check-chars=ЧИСЛО

Позволяет сравнивать на уникальность указанное ЧИСЛО символов в каждой строке:

$ echo -e перестройка\\nпеределка\\nперестрелка | uniq -w4

перестройка

Работает эта опция и в сочетании с опциями пропуска слов или символов:

$ echo -e перестройка\\nпеределка\\nперестрелка | uniq -s2 -w2

перестройка
Опции --help и --version общеизвестны, останавливаться на них мы не будем.

Остается добавить, что команда uniq принимает в качестве аргументов не только файлы, которые проверяются на уникальность, но и файлы, куда результат проверки будет записан:

$ uniq имя_файла_входящего имя_файла_выходящего

Команда uniq и символы кириллицы

Новые версии программы с русскими буквами работают адекватно (версия 5.97 с некоторыми опциями неадекватно обращалась с кириллицей; версия 6.4 никаких нареканий не вызывает).

Резюме команды uniq

Сырая и не самая необходимая команда (несмотря на маститых авторов: Richard Stallman и David MacKenzie). Следует обновить до новейшей версии, так как в версии 5.97 замечены ошибки. Для отбраковки одинаковых строк советую, вместо команды uniq, применять команду sort -u.



Приложение

Список статей цикла HuMan: