Библиотека сайта rus-linux.net
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.