- команда uniq не работает должным образом?
- Команда uniq Linux
- Синтаксис uniq
- Опции uniq
- Примеры использования uniq
- Выводы
- 13 инструментов для обработки текста в командной оболочке
- Содержание
- Обработка текста в командной оболочке
- paste
- Замена текста
- Реальные примеры
- Фильтрация CSV с помощью grep и awk
- Вывод адреса IPv4, связанного с сетевым интерфейсом
- Извлечение значения из файла конфигурации
- Извлечение IP-адресов из файла журнала
- Переименование функции в исходном файле
- Углубляемся: циклы for и xargs
- Резюме
- Что дальше
команда uniq не работает должным образом?
Итак, я проверяю md5 хэш моих файлов с этим как мой вывод:
Однако после запуска, find . -type f -exec md5sum ‘<>‘ ‘;’ | uniq -w 33 чтобы найти уникальные хеши, я получаю это:
Насколько я понимаю, только один из них derpina.txt или derp.txt должен отображаться, поскольку их хэши одинаковы. Я что-то пропустил? Может кто-нибудь просветить меня, почему это выводит, как это?
Вы должны использовать sort перед uniq :
uniq удаляет только повторяющиеся строки Он не переупорядочивает строки в поисках повторов. sort делает эту часть.
Это задокументировано в man uniq :
Примечание: «uniq» не обнаруживает повторяющиеся строки, если они не являются смежными. Вы можете сначала отсортировать ввод или использовать sort -u’ without uniq ‘.
Вход для uniq должен быть отсортирован. Так что для примера,
должно сработать. -w ( —check-chars=N ) Делает линии уникальными только в отношении первого столбца; Эта опция работает для этого случая. но возможности указать соответствующие части линии uniq ограничены. Например, нет опций для указания работы с некоторыми столбцами 3 и 5, игнорируя столбец 4.
У команды sort есть опция для уникальных строк вывода, а строки уникальны относительно ключей, используемых для сортировки. Это означает, что мы можем использовать мощный синтаксис ключа, sort чтобы определить, в какой части строки должны быть уникальными.
дает точно такой же результат, но sort часть более гибкая для других целей.
Источник
Команда uniq Linux
Команда uniq предназначена для поиска одинаковых строк в массивах текста. При этом с найденными совпадениями пользователь может совершать множество действий — например, удалять их из вывода либо наоборот, выводить только их.
Работа команды осуществляется как с текстовыми файлами (в том числе, записями скриптов), так и с текстом, напечатанным в командной строке терминала.
Синтаксис uniq
Запись команды осуществляется следующим образом:
$ uniq опции файл_источник файл_для_записи
Файл источник указывает откуда надо читать данные, а файл для записи — куда писать результат. Но их указывать не обязательно. В примерах мы будем набирать текст, который нуждается в редактировании, прямо в командную строку терминала, воспользовавшись ещё одной командой — echo, и применив к ней опцию -e. Это будет выглядеть так:
echo -e [текст, слова в котором разделены управляющей последовательностью\\n] | uniq
Эта управляющая последовательность нужна, чтобы указать утилите, что каждое слово выводится в новой строке. Если указано только название файла источника, результат выполнения команды появится прямо в окне терминала. А при наличии выходного файла текст будет напечатан в теле документа.
Опции uniq
У команды uniq есть такие основные опции:
- -u (—unique) — выводит исключительно те строки, у которых нет повторов.
- -d (—repeated) — если какая-либо строка повторяется несколько раз, она будет выведена лишь единожды.
- -D — выводит только повторяющиеся строки.
- —all-repeated[=МЕТОД] — то же самое, что и -D, но при использовании этой опции между группами из одинаковых строк при выводе будет отображаться пустая строка. [=МЕТОД] может иметь одно из трех значений — none (применяется по умолчанию), separate или prepend.
- —group[=МЕТОД] — выводит весь текст, при этом разделяя группы строк пустой строкой. [=МЕТОД] имеет значения separate (по умолчанию), prepend, append и both, среди которых нужно выбрать одно.
Вместе с основными опциями могут применяться дополнительные. Они нужны для более тонких настроек работы команды:
- -f (—skip-fields=N) — будет проведено сравнение полей, начиная с номера, который следует после указанного вместо буквы N. Поля — это слова, хотя, называть их словами в прямом смысле слова нельзя, ведь словом команда считает любую последовательность символов, отделенную от других последовательностей пробелом либо табуляцией.
- -i (—ignore-case) — при сравнении не будет иметь значение регистр, в котором напечатаны символы (строчные и заглавные буквы).
- -s (—skip-chars=N) — работает по аналогии с -f, однако, игнорирует определенное количество символов, а не строк.
- -c (—count) — в начале каждой строки выводит число, которое обозначает количество повторов.
- -z (—zero-terminated) — вместо символа новой строки при выводе будет использован разделитель строк NULL.
- -w (—check-chars=N) — указание на то, что нужно сравнивать только первые N символов в строках.
Примеры использования uniq
Прежде всего следует отметить главную особенность команды uniq — она сравнивает только строки, которые находятся рядом. То есть, если две строки, состоящие из одинакового набора символов, идут подряд, то они будут обнаружены, а если между ними расположена строка с отличающимся набором символов — то не будут поэтому перед сравнением желательно отсортировать строки с помощью sort. Без задействования файлов uniq работает так:
echo -e небо\\nоблака\\nоблака\\nоблака\\nсолнце\\nзвезды | uniq
После команды uniq можно использовать её опции. Вот пример вывода, где не просто удалены повторы, но и указано количество одинаковых строк:
echo -e небо\\nоблака\\nоблака\\nоблака\\nсолнце\\nзвезды | uniq -c
Теперь применим команду к тексту, который находится в файле.
uniq —all-repeated=prepend text-example.txt
Как можно заметить, глядя на снимок экрана, команда вывела в качестве повторяющихся только вторую и третью группу строк.
Причина этого — незаметный глазу символ пробела, который стоит в конце одной из строк первой группы. Нужно быть предельно внимательным при использовании uniq, чтобы получить качественный результат.
Используемая опция —all-repeated=prepend выполнила свою работу — добавила пустые строки в начало, в конец и между группами строк. Теперь попробуем сравнить только первые 5 символов в каждой строке.
echo -e небо исполосовано молниями\\nоблака на небе\\nоблака разогнал ветер\\nоблака закрыли солнце\\nсолнце светит ярко\\nзвезды кажутся огромными | uniq -w5
Как видно на скриншоте, повторяющиеся строки, которые начинались словом «облака», были удалены. Осталась только первая из них. Вывод только уникальных строк с использованием опции -u выглядит так:
echo -e небо\\nоблака\\nоблака\\nоблака\\nсолнце\\nзвезды | uniq -u
Чтобы проигнорировать определенное количество символов в начале одинаковых строк, воспользуемся опцией —skip-chars. В данном случае команда пропустит слово «облака», сравнив слова «перистые» и «белые».
echo -e небо\\nоблака перистые\\nоблака перистые\\nоблака белые\\nсолнце\\nзвезды | uniq —skip-chars=6
А вот наглядная демонстрация отличий при использовании опции —group с разными значениями. both добавило пустые строки как перед текстом, так и после него, а также между группами строк.
echo -e небо\\nоблака\\nоблака\\nоблака\\nсолнце\\nзвезды | uniq —group=both
Тогда как append не добавило пустую строку перед текстом:
echo -e небо\\nоблака\\nоблака\\nоблака\\nсолнце\\nзвезды | uniq —group=append
Выводы
Команда uniq linux пригодится тем, кто часто и много работает с массивами текста, не имея возможности вычитывать их самостоятельно. Следует заметить, что не все версии uniq работают исправно, поэтому иногда результат выдачи может отличаться от ожидаемого.
Свои вопросы относительно использования команды, а также замечания и пожелания оставляйте в комментариях.
Источник
13 инструментов для обработки текста в командной оболочке
Здесь представлен фрагмент будущей книги «Основные инструменты и практики для начинающего разработчика программного обеспечения» Бальтазара Рубероля и Этьена Броду. Книга должна помочь образованию подрастающего поколения разработчиков. Она охватит такие темы, как освоение консоли, настройка и эффективная работа в командной оболочке, управление версиями кода с помощью git , основы SQL, инструменты вроде Make , jq и регулярные выражения, основы сетевого взаимодействия, а также лучшие практики разработки программного обеспечения и совместной работы. В настоящее время авторы упорно работают над этим проектом и приглашают всех поучаствовать в списке рассылки.
Содержание
Обработка текста в командной оболочке
Одна из причин, которые делают командную оболочку бесценным инструментом, — это большое количество команд обработки текста и возможность легко объединять их в конвейер, создавая сложные шаблоны обработки. Эти команды делают тривиальными многие задачи по анализу текста и данных, преобразованию данных между разными форматами, по фильтрации строк и т. д.
При работе с текстовыми данными главный принцип заключается в том, чтобы разбить любую сложную проблему на множество более мелких — и решить каждую из них с помощью специализированного инструмента.
Заставьте каждую программу хорошо выполнять одну функцию — «Основы философии Unix»
Примеры из этой главы на первый взгляд могут показаться немного надуманными, но это сделано специально. Каждый из инструментов разработан для решения одной небольшой задачи. Однако в сочетании они становятся чрезвычайно мощными.
Мы рассмотрим некоторые из наиболее распространенных и полезных команд обработки текста в командной оболочке и продемонстрируем реальные рабочие процессы, соединяющие их вместе. Я предлагаю взглянуть на маны этих команд, чтобы увидеть всю широту возможностей в вашем распоряжении.
Файл CSV с примерами доступен в онлайне. Можете скачать его для проверки материала.
Команда cat используется для составления списка из одного или нескольких файлов и отображения их содержимого на экране.
head выводит первые n строк в файле. Это может быть очень полезно для того, чтобы заглянуть в файл неизвестной структуры и формата, не заваливая всю консоль кучей текста.
Если -n не указано, head выводит первые десять строк указанного файла или входящего потока.
tail — аналог head , только он выводит последние n строк в файле.
Если хотите вывести все строки, расположенном после n-й строки (включая её), можете использовать аргумент -n +n .
В нашем файле 43 строки, поэтому tail -n +42 выводит только 42-ю и 43-ю строки из него.
Если параметр -n не указан, tail выведет последние десять строк в указанном файле или входном потоке.
tail -f или tail —follow отображают последние строки в файле и каждую новую строку по мере записи в файл. Это очень полезно для просмотра активности в реальном времени, например, что записывается в логи веб-сервера и т. д.
wc (word count) выводит количество символов ( -c ), слов ( -w ) или строк ( -l ) в указанном файле или потоке.
По умолчанию отображается всё вышеперечисленное.
Если текстовые данные передаются по конвейеру или перенаправлены в stdin , то отображается только счётчик.
grep — это швейцарский нож фильтрации строк по заданному шаблону.
Например, можем найти все вхождения слова mutex в файле.
grep может обрабатывать либо файлы, указанные в качестве аргументов, либо поток текста, переданный на его stdin . Таким образом, мы можем сцеплять несколько команд grep для дальнейшей фильтрации текста. В следующем примере мы фильтруем строки в нашем файле metadata.csv , чтобы найти строки, содержащие и mutex, и OS.
Рассмотрим некоторые опции grep и их поведение.
grep -v выполняет инвертное сопоставление: фильтрует строки, которые не соответствуют шаблону аргументов.
grep -i выполняет сопоставление без учёта регистра. В следующем примере grep -i os находит как OS, так и os.
grep -l выводит список файлов, содержащих совпадение.
Команда grep -c подсчитывает, сколько раз найден образец.
grep -r рекурсивно ищет файлы в текущем рабочем каталоге и всех его подкаталогах.
grep -w показывает только совпадающие целиком слова.
cut извлекает часть файла (или, как обычно, входного потока). Команда определяет разделитель полей (который разделяет столбцы) с помощью опции -d , а порядковые номера столбцов для извлечения с помощью опции -f .
Например, следующая команда извлекает первый столбец из последних пяти строк нашего CSV-файла.
Поскольку мы имеем дело с CSV, то столбцы разделяются запятой, а за извлечение первого столбца отвечает опция -f 1 .
Можно выбрать и первый, и второй столбцы, используя опцию -f 1,2 .
paste
paste объединяет вместе два разных файла в один многоколоночный файл.
По умолчанию paste использует разделитель табуляции, но его можно изменить с помощью параметра -d .
Ещё один распространённый способ использования paste — объединение всех строк в потоке или файле с помощью заданного разделителя, используя комбинацию аргументов -s и -d .
Если в качестве входного файла указан параметр — , то вместо него будет считываться stdin .
Команда sort , собственно, сортирует данные (в указанном файле или входном потоке).
sort -r выполняет обратную сортировку.
sort -n сортирует поля по их арифметическому значению.
uniq обнаруживает и отфильтровывает соседние одинаковые строки в указанном файле или входном потоке.
Поскольку uniq отфильтровывает только соседние строки, в наших данных могут ещё остаться дубликаты. Чтобы отфильтровать все одинаковые строки из файла, нужно сначала отсортировать его содержимое.
uniq -c в начале каждой строки вставляет количество её вхождений.
uniq -u отображает только уникальные строки.
Примечание. uniq особенно полезен в сочетании с сортировкой, поскольку конвейер | sort | uniq позволяет удалить все дублирующиеся строки в файле или потоке.
awk — это чуть больше, чем просто инструмент обработки текста: на самом деле у него целый язык программирования. В чём awk действительно хорош — так это в разбиении файлов на столбцы, и делает это с особенным блеском, когда в файлах перемешаны пробелы и табы.
Примечание. cat -t отображает табы как ^I .
Как видим, столбцы разделены либо пробелами, либо табуляциями, и не всегда одинаковым количеством пробелов. cut здесь бесполезен, потому что работает только с одним символом-разделителем. Но awk легко разберётся с таким файлом.
awk ‘< print $n >‘ выводит n-й столбец в тексте.
Хотя awk способен на гораздо большее, выдача колонок составляет, наверное, 99% вариантов использования в моём личном случае.
Примечание. < print $NF >выводит последний столбец в строке.
tr расшифровывается как translate. Эта команда заменяет одни символы на другие. Она работает либо с символами, либо с классами символов, такими как строчные, печатные, пробелы, буквенно-цифровые и т. д.
На стандартных входных данных tr заменяет все вхождения на .
tr может переводить классы символов с помощью нотации [:class:] . Полный список доступных классов описан на справочной странице tr , но некоторые продемонстрируем здесь.
[:space:] представляет все типы пробелов, от простого пробела до табуляции или символа новой строки.
Все символы, похожие на пробелы, переведены в запятую. Обратите внимание, что символ % в конце выдачи означает отсутствие завершающей новой строки. Действительно, этот символ тоже переведён в запятую.
[:lower:] представляет все строчные символы, а [:upper:] — все прописные. Таким образом, преобразование между ними становится тривиальным.
tr -c SET1 SET2 преобразует любой символ, не входящий в набор SET1, в символы набора SET2. В следующем примере все символы, кроме указанных гласных, заменяются пробелами.
tr -d удаляет указанные символы, а не заменяет их. Это эквивалент tr » .
tr также может заменить диапазоны символов, например, все буквы между a и e или все числа между 1 и 8, используя нотацию s-e , где s — начальный символ, а e — конечный.
Команда tr -s string1 сжимает все множественные вхождения символов в string1 в одно-единственное. Одним из наиболее полезных применений tr -s является замена нескольких последовательных пробелов одним.
Команда fold сворачивает все входные строки до заданной ширины. Например, может быть полезно убедиться, что текст помещается на дисплеях небольшого размера. Так, fold -w n укладывает строки по ширине n символов.
Команда fold -s будет разбивать строки только на символах пробела. Её можно объединить с предыдущей, чтобы ограничить строким заданным количеством символом.
sed — это неинтерактивный потоковый редактор, который используется для преобразования текста во входном потоке строка за строкой. В качестве входных данных используется или файл, или stdin , а на выходе тоже или файл, или stdout .
Команды редактора могут включать один или несколько адресов, функцию и параметры. Таким образом, команды выглядят следующим образом:
Хотя sed выполняет множество функций, мы рассмотрим только замену текста как один из самых распространённых вариантов использования.
Замена текста
Команда замены sed выглядит следующим образом:
Пример: замена первого экземпляра слова в каждой строке в файле:
Мы видим, что в первой строчке заменяется только первый экземпляр hello . Чтобы заменить все вхождения hello во всех строках, можно использовать опцию g (означает global).
sed позволяет использовать любые разделители, кроме / , что особенно улучшает читаемость, если в самих аргументах команды есть слэши.
Адрес говорит редактору, в какой строке или диапазоне строк выполнять подстановку.
Адрес 1 указывает заменять hello на Hey I just met you в первой строке. Можем указать диапазон адресов в нотации , , где может быть либо номером строки, либо $ , то есть последней строкой в файле.
По умолчанию sed выдаёт результат в свой stdout , но может отредактировать и оригинальный файл с опцией -i .
Примечание. В Linux достаточно только -i . Но в macOS поведение команды немного отличается, поэтому сразу после -i нужно добавить » .
Реальные примеры
Фильтрация CSV с помощью grep и awk
В этом примере grep в файле metadata.csv сначала фильтрует строки, содержащие слово gauge , затем те, у которых query в четвёртой колонке, и выводит название метрики (1-я колонка) с соответствующим значением per_unit_name (5-я колонка).
Вывод адреса IPv4, связанного с сетевым интерфейсом
Команда ifconfig выводит сведения по указанному сетевому интерфейсу. Например:
Затем запускаем grep для inet , что выдаст две строки соответствия.
Затем с помощью grep -v исключаем строку с ipv6 .
Наконец, с помощью awk запрашиваем второй столбец в этой строке: это IPv4-адрес, связанный с нашим сетевым интерфейсом en0 .
Примечание. Мне предложили заменить grep inet | grep -v inet6 такой надёжной командой awk :
Она короче и конкретно нацелена на IPv4 с условием $1 == «inet» .
Извлечение значения из файла конфигурации
В файле конфигурации git текущего пользователя ищем значение editor = , обрезаем знак = , извлекаем второй столбец и удаляем все пробелы вокруг.
Извлечение IP-адресов из файла журнала
Следующий реальный код ищет в журнале БД сообщение Too many connections from (за ним следует IP-адрес) и отображает десять главных нарушителей.
Давайте разберем, что делает этот конвейер. Во-первых, как выглядит строка в журнале.
Затем awk ‘< print $12 >‘ извлекает из строки IP-адрес.
Команда sed ‘s@/@@’ удаляет начальный слэш.
Примечание. Как мы уже видели ранее, в sed можно использовать любой разделитель. Хотя обычно в качестве разделителя используется / , здесь мы заменяем именно этот символ, что слегка ухудшит читаемость выражения подстановки.
sort | uniq -c сортирует IP-адреса в лексикографическом порядке, а затем удаляет дубликаты, добавляя перед IP-адресами количество вхождений каждого.
sort -rn | head -n 10 сортирует строки по количеству вхождений, численно и в обратном порядке, чтобы главные нарушители выводились в первую очередь, из которых отображаются 10 строк. Последняя команда awk < print $2 >извлекает сами IP-адреса.
Переименование функции в исходном файле
Представим, что мы работаем над проектом и хотели бы переименовать недачно названную функцию (или класс, переменную и т. д.) в исходном файле. Можно сделать это с помощью команды sed -i , которая выполняет замену прямо в оригинальном файле.
Примечание. На macOS вместо sed -i используйте sed -i » .
Однако мы переименовали функцию только в оригинальном файле. Это сломает импорт bool_from_str в любом другом файле, поскольку эта функция больше не определена. Нужно найти способ переименовать bool_from_str повсюду в нашем проекте. Такого можно добиться с помощью команд grep , sed , а также циклов for или с помощью xargs .
Углубляемся: циклы for и xargs
Чтобы заменить в нашем проекте все вхождения bool_from_str , сначала нужно рекурсивно найти их с помощью grep -r .
Поскольку нас интересуют только файлы c совпадениями, также необходимо использовать опцию -l/—files-with-matches :
Затем можем использовать команду xargs для осуществления действий с каждой строки выходных данных (то есть всех файлов, содержащих строку bool_from_str ).
Опция -n 1 указывает, что каждая строка в выходных данных должна выполнить отдельную команду sed .
Затем выполняются следующие команды:
Если команда, которую вы вызываете с помощью xargs (в нашем случае sed ), поддерживает несколько аргументов, то следует отбросить аргумент -n 1 для производительности.
Эта команда затем исполнит
Примечание. Из синопсиса sed на ман-странице видно, что команда может принять несколько аргументов.
Действительно, как мы видели в предыдущей главе, file . означает, что принимаются несколько аргументов, представляющих собой имена файлов.
Мы видим, что произведены замены для всех вхождений bool_from_str .
Как это часто бывает, существует несколько способов достижения одного и того же результата. Вместо xargs мы могли бы использовать циклы for , чтобы перебирать строки по списку и выполнять действие над каждым элементом. У этих циклов такой синтаксис:
Если обернуть нашу команду grep в $() , то оболочка выполнит её в подоболочке, результат чего затем будет повторён в цикле for .
Эта команда выполнит
Синтаксис циклов for кажется мне более чётким, чем у xargs , однако последняя может выполнять команды параллельно, используя параметры -P n , где n — максимальное количество параллельных команд, выполняемых одновременно, что может дать выигрыш в производительности.
Резюме
Все эти инструменты открывают целый мир возможностей, так как позволяют извлекать и преобразовывать данные, создавая целые конвейеры из команд, которые, возможно, никогда не предназначались для совместной работы. Каждая из них выполняет относительно небольшую функцию (сортировка sort , объединение cat , фильтры grep , редактирование sed , вырезание cut и т. д.).
Любую задачу, включающую текст, можно свести к конвейеру более мелких задач, каждая из которых выполняет простое действие и передаёт свои выходные данные в следующую задачу.
Например, если нам хочется узнать, сколько уникальных IP-адресов в файле журнала, и чтобы эти IP-адреса всегда появлялись в одном и том же столбце, то можно запустить следующую последовательность команд:
- grep строк, которые соответствуют шаблону строк с IP-адресами
- найти столбец с IP-адресом, извлечь его с помощью awk
- отсортировать список IP-адресов с помощью sort
- устранить смежные дубликаты с помощью uniq
- подсчитать количество строк (то есть уникальных IP-адресов) с помощью wc -l
Поскольку есть множество нативных и сторонних инструментов обработки текста, также много способов решить любую задачу.
Примеры в этой статье были надуманными, но я предлагаю вам прочитать удивительную статью «Инструменты командной строки могут быть в 235 раз быстрее, чем ваш кластер Hadoop», чтобы получить представление о том, насколько полезны и мощны эти команды на самом деле и какие реальные проблемы они могут решить.
Что дальше
- Подсчитайте количество файлов и каталогов, расположенных в вашем домашнем каталоге.
- Отобразите содержимое файла только прописными буквами.
- Подсчитайте, сколько раз встречалось каждое слово в файле.
- Подсчитайте количество гласных в файле. Отсортируйте результат от наиболее распространённой до наименее распространённой буквы.
Будущая книга «Основные инструменты и практики для начинающего разработчика программного обеспечения» (Essential Tools and Practices for the Aspiring Software Developer) Бальтазара Рубероля и Этьена Броду поможет создать продуктивную среду разработки и познакомиться с полезными инструментами и практиками, которые нужны для профессионального роста. Как уже было сказано, она охватит такие темы, как освоение терминала, настройка и эффективная работа в командной оболочке, управление версиями кода с помощью git , основы SQL, инструменты вроде Make , jq и регулярные выражения, основы сетевого взаимодействия, а также лучшие практики разработки программного обеспечения и совместной работы.
Если интересно поучаствовать в проекте, подписывайтесь на список рассылки!
Источник