Uniq

Материал из Ай да Linux Wiki
Перейти к навигации Перейти к поиску

Описание

uniq — утилита Unix, с помощью которой можно вывести или отфильтровать повторяющиеся строки в файле. Если входной файл задан как («-») или не задан вовсе, чтение производится из стандартного ввода. Если выходной файл не задан, запись производится в стандартный вывод. Вторая и последующие копии повторяющихся соседних строк не записываются. Повторяющиеся входные строки не распознаются, если они не следуют строго друг за другом, поэтому может потребоваться предварительная сортировка файлов.

Использование

 uniq [-c | -d | -u] [-i] [-f число_полей] [-s число_символов] [входной_файл [выходной_файл]]

Опции программы имеют следующие значения:

-u Выводить только те строки, которые не повторяются на входе.

-d Выводить только те строки, которые повторяются на входе.

-c Перед каждой строкой выводить число повторений этой строки на входе и один пробел.

-i Сравнивать строки без учёта регистра.

-s число_символов

Игнорировать при сравнении первые число_символов символов каждой строки ввода. Если эта опция указана совместно с -f, то будут игнорироваться первые число_полей полей, а затем ещё число_символов символов. Символы также нумеруются начиная с единицы.

-f число_полей

Игнорировать при сравнении первые число_полей полей каждой строки ввода. Полем является строка непробельных символов, отделённая от соседних полей пробельными символами. Поля нумеруются начиная с единицы.

Команда 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.

Параметры uniq

Опция -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.



Информация взята с open-club.ru