- Команда uniq Linux
- Синтаксис uniq
- Опции uniq
- Примеры использования uniq
- Выводы
- Количество файлов в папке Linux
- Как посмотреть количество файлов в папке Linux
- Количество файлов в папке с помощью tree
- Выводы
- [Bash] Поиск строк с общими полями и подсчет количества совпадений
- Страдаю какой-то херней вместо приготовления ужина
Команда 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 работают исправно, поэтому иногда результат выдачи может отличаться от ожидаемого.
Свои вопросы относительно использования команды, а также замечания и пожелания оставляйте в комментариях.
Источник
Количество файлов в папке Linux
Мы уже говорили о многих командах Linux, которые вы можете использовать для того, чтобы сделать свою работу с этой системой проще. В сегодняшней статье поговорим о такой вещи, которая становится нужной не очень часто. Сегодня мы рассмотрим как посчитать количество файлов в папке Linux различными способами с помощью разных команд.
Это может быть полезно во многих случаях, например, при написании различных скриптов и других подобных работ. Я попытаюсь охватить все возможные способы сделать это в терминале.
Как посмотреть количество файлов в папке Linux
Самый простой способ решить эту задачу — использовать утилиту ls вместе с утилитой wc. Они покажут сколько файлов находится в текущей папке:
В моем случае утилита выдала результат 21, но поскольку ls выводит размер всех файлов в папке строкой total, то у нас файлов на один меньше. Нужно учесть, что тут отображаются еще и директории. Каждая директория начинается с символа «d», а каждый файл с «-«. Для символических ссылок используется «l». Посмотрите внимательно на вывод ls:
Чтобы их отсеять используйте grep:
ls -l | grep «^-» | wc
Эта конструкция выберет только те строки, которые начинаются на дефис. Если вас интересуют не только обычные файлы, но и скрытые, то можно использовать опцию -a:
ls -la | grep «^-» | wc
Так можно подсчитать количество папок:
ls -la | grep ^d | wc
А так символических ссылок:
ls -la | grep ^l | wc
Если вам нужно подсчитать количество файлов во всех подпапках, то можно использовать опцию -R:
ls -laR | grep «^-» | wc
С фильтром только файлы нам уже не страшно, что команда будет выводить служебную информацию. Если вы не хотите использовать ls, можно воспользоваться утилитой find:
find . -maxdepth 1 -type f | wc
Если нужно смотреть не только количество файлов в папке, но и подпапок, просто не нужно использовать -type f:
find . -maxdepth 1 | wc
Только папки отдельно:
find . -maxdepth 1 -type d | wc
А в случае, когда необходимо перебрать все файлы во всех подпапках, не устанавливайте параметр -maxdepth:
Все эти команды это очень хорошо, но есть еще одно, более удобное средство посчитать количество файлов linux, это утилита tree.
Количество файлов в папке с помощью tree
Утилита tree выводит дерево файлов и папок, а потом подсчитывает их количество по отдельности. Кроме того, утилита имеет множество опций и настроек. Но она не поставляется в системе по умолчанию. Для ее установки в Ubuntu выполните:
$ sudo apt install tree
Синтаксис утилиты очень прост:
$ tree опции каталог
Теперь разберем ее основные опции:
- -a — выводить все файлы, включая файлы, которые начинаются на точку;
- -d — выводить только директории;
- -l — открывать символические ссылки;
- -f — выводить полный путь к файлу;
- -x — оставаться только в пределах этого раздела, не переходить по точкам монтирования;
- -L — устанавливает максимальный уровень вложенности;
- -P — выбирать только те файлы и папки, которые подходят под регулярное выражение;
- -I — не выводить файлы, которые подходят под регулярное выражение;
- —prune — не выводить пустые папки;
- -o — записать вывод в файл;
В утилиты есть еще опции по сортировке выводимого дерева и по формату вывода имен файлов, но мы не будем их рассматривать, поскольку нас интересует только количество файлов в папке Linux. Сначала считаем количество файлов и папок во всех подпапках:
Теперь только в текущей, задаем максимальную вложенность равной единице:
Еще можем включить вывод всех файлов, включая скрытые:
Или выберем только те, которые содержат второй символ в имени «a»:
Выводы
В этой небольшой статье мы рассмотрели как посмотреть количество файлов в папке Linux. Как видите, это очень просто. Надеюсь, эта информация была полезной для вас. Если у вас остались вопросы, спрашивайте в комментариях!
Источник
[Bash] Поиск строк с общими полями и подсчет количества совпадений
Доброго времени суток!
Нуждаюсь в помощи опытных коллег.
Есть файл такого содержания
- Иван:Петров
- Сергей:Петров
- Виктор:Петров
- Вадим:Петров
- Алексей:Петров
- Станислав:Сидоров
- Вячеслав:Сидоров
- Геннадий:Сидоров
- Владимир:Сидоров
- Арсений:Сидоров
- Константин:Иванов
- Дмитрий:Иванов
- Игорь:Иванов
Мне нужно подсчитать кол-во совпадений второго поля и найти строки в которых кол-во совпадений n меньше заданного N в скрипте (в данном случае 5) и использовать второе поле из этих строк в качестве переменной $var_surname для дальнейших действий.
на выходе нужно получить
Буду благодарен любым подсказкам.
1. идешь while-ом по строке 2. пишешь функцию, подсчета совпадений 3. на каждой итерации, бери фамилию. разделитель двоеточие передавай в функцию поиска из пункта 2 (awk -F ‘:’ ‘
Вырезаешь второе поле man cut или man grep . Сортируешь man sort . Считаешь каждое входение man uniq . Получаешь список «кол-во фамилия». Дальше сам
Как говорит тут один аноним, сразу видно пятизвёздочного. Ну накой awk -F ‘:’ ‘
Спасибо, очень помог) Простое и доступное для меня решение.
cat unionfile | cut -d»:» -f2 | sort | uniq -c > output
sed -i ‘s/^ *//’ output
awk -F ‘[()]’ ‘$1 ( 21.07.19 16:12:49 )
Раз тут идет звездная война, а ТС, как я понимаю, ничего не понимает, то если дать почти готовое решение, это ничего не изменить в балансе темных и светлых сил. «` cut -d: -f2 | sort | uniq -c «` И вообще, причем тут баш, сед, авк и другие. Задача именно на понимание.
Ну ты понял, что я ошибся на счет теба. Успехов.
Возможно для больших объемов данных не пойдет и есть решения изящнее и производительнее, но для моего случая и это сработает.
Это точно будет попроизводительнее перелопачивания на баш.
Хорошо, если так можно сделать в bash, сходу и без лишних телодвижений. Я не в курсе и выдал сходу, по памяти.
Здесь sed-ом сначала удаляю пробелы вначале строки, потом с помощью awk по оставляю только строки где количество совпадений меньше заданного (значение в первом поле ( 21.07.19 17:05:25 )
Мне количество совпадений важно обязательно считать в переменную т.к. я потом произвожу с ней математическое действие. Где ты производишь мат. действия? Если в баше, то читай сразу в баш и фильтруй там.
Мне количество совпадений важно обязательно считать в переменную т.к. я потом произвожу с ней математическое действие.
Где ты производишь мат. действия? Если в баше, то читай сразу в баш и фильтруй там.
Мне количество совпадений важно обязательно считать в переменную т.к. я потом произвожу с ней математическое действие.
Спасибо) Протестировал данное решение тоже, все работает.
Только вот выдает строки с совпадениями n не только те, которые меньше заданного значения, но и которые равны этому значению.
Для простых обработок текста есть специальный язык.
Только вот выдает строки с совпадениями n не только те, …
Ясно, пациент полный ноль в баше.
Раз мы для тебя стараемся, сделай для нас что-нибудь. Например, какая самая популярная фамилия?
Только вот выдает строки с совпадениями n не только те, которые меньше заданного значения, но и которые равны этому значению.
Потому там и 4, а не 5. Но если вам для зачёта надо, то поменяйте le, на lt.
Спасибо за пример, познавательно.
Правда отдельной программой не очень удобно, т.к. этот кусочек обработки является частью более глобального скрипта и хочется все в одном файле уместить.
Не, я не сдаю зачеты, я для своих задач пишу и учусь)
Думаю разобрался бы, выше был пример с -t вместо -e и читал я ранее, что -e это equal, но в любом случае спасибо за поправку.
И вообще всем отписавшимся — спасибо большое за то что подсказали как можно решить задачу разными способами. Добра вам всем. Хорошо, что есть такие отзывчивые люди, которым не лень кому-то менее опытному подсказать)
p.s. ну не полный ноль, скрипты пишу какие-то для себя, повышаю сложность. Но вот с массивами очень плотно пока не работал, знакомлюсь как раз.
На будущее — прочитай Advanced Bash Scripting Guide. Он есть и на русском(правда устаревший перевод), но тебе хватит. Оттуда и будет понятна в чём разница между -lt и -le и где можно обойтись встроенными средствами bash(если переносимость на другие шеллы не планируется), а где надо подключать внешние программы.
Ну а потом — только практика. И чтение чужого кода, да.
Правда отдельной программой не очень удобно
хочется все в одном файле уместить.
ну это так себе хотелка. Не зря индустрия больше полусотни лет разбивает программы на осмысленные части. Но пока твой скрипт не слишком велик программу на awk можно внедрить прямо в него
А вот не соглашусь. Сравните свой код и мой чуть выше. Есть разница? Казалось бы в принципе почти одно и тоже и даже может awk тут будет и быстрее. Но, это пока вам не понадобится потом работать с полученными переменными, особенно если надо будет обрабатывать чуть ли весь ассоциативный массив гораздо дальше, чем можно поместить в этот внедренный код в сложный скрипт.
Но, это пока вам не понадобится потом работать с полученными переменными
Объявление запрошенных ТСом переменных в рамках этого скрипта, думаю, излишне (либо мало данных). Что будет, если попадется 2 фамилии с n ★★★★★ ( 21.07.19 23:40:04 )
Последнее исправление: YAR 21.07.19 23:44:10 (всего исправлений: 2)
Что будет, если попадется 2 фамилии с n ★★★★★ ( 21.07.19 23:57:07 )
смысл тогда в awk
Где удобство и скорость?
По удобству — пусть каждый под задачу выбирает удобный для себя вариант. По скорости — awk будет быстрее на больших объемах данных.
Если у ТСа задача все равно подразумевает использование баша (некие математические операции с переменными — и да, а зачем тут баш?) — это не повод решать все исключительно средствами баша, благо подзадачи можно реализовать различными средствами.
По скорости — awk будет быстрее на больших объемах данных.
Да с чего бы это было б сильно заметно? Оба языка, что bash, что awk работают примерно одинаково — парсят текст, создают дерево разбора и его интерпретируют. Я знаю, что там внутри и даже правил и то и другое. У awk есть хорошее преимущество, когда надо обрабатывать входные строки через regex-ы. Когда же у нас задача разбить входные строки на два поля, то применение awk как правило только доказывает непрофессионализм пишущего.
Страдаю какой-то херней вместо приготовления ужина
Да с чего бы это было б сильно заметно?
Страдаю какой-то херней вместо приготовления ужина
Дык. Аж целых 2 минуты жевало, а с первого коммента — уже более 2 часов. Если вам жалко 2 минут на 121Мб, то перепишите на C. Не удивлюсь, что bash тормозит на генерации ассоциативного индекса.
На всякий случай, напоминаю, что я никогда не говорил, что bash на этой задаче может быть быстрее. Я говорил, что если вам понадобится потом эти данные, то встраивание другого интерпретатора в скрипт неудобно и будет скорее всего медленнее. Ну в самом деле, вот пусть у вас 100M будет по 4 имен у фамилий и только одно 5. Ну прогоните через пайп и while read.
Да с чего бы это было б сильно заметно?
я никогда не говорил, что bash на этой задаче может быть быстрее.
Это не «не сильно заметно». Это не «чуть быстрее». Это разница в 200 раз.
Чем что? 2 последовательных цикла на bash по 3 минуты будут быстрее, чем 0.7 секунды на mawk + 3 минуты на bash? Ну ок.
Дальше можно было не писать:
Когда же у нас задача разбить входные строки на два поля, то применение awk как правило только доказывает непрофессионализм пишущего
Это не «не сильно заметно». Это не «чуть быстрее». Это разница в 200 раз.
Как вы предсказуемы. На реальных данных, когда вообще имеет смысл пользоваться скриптами, разница в долях секунд не заметна.
А вот это уже подлог. Я вам предлагал обработать задачу awk, а потом закачать весь массив через read. Собственно данных уже достаточно, чтобы увидеть, что будет медленнее.
Добрый день. Вы оказались правы, когда продвинулся дальше, то оказалось, что был один неучтенный момент в логике скрипта и понадобилось помимо «фамилии» и кол-ва совпадений извлекать еще и полностью строки удовлетворяющие данному условию.
А вот как это сделать в контексте вашего примера никак не разберусь. Подключать еще один массив?
Справедливости ради, обсуждалось абстрактное условие: «если вдруг. » 🙂
Так как в bash нет многомерных массивов, а их ручная эмуляция весьма кривая как по виду кода так и по скорости, то новые массивы обычно наилучшее решение. Если б не одно но, которое у вас: ассоциативный массив у вас не сохраняет порядок следования входным данным и придётся решать задачу конкретно по ситуации, может даже вначале заполнять данными обычные, а потом отдельно высчитывать с ассоциативными.
Ты занимаешься не тем делом. Ты пытаешься работать с базой данных на скриптовом языке, который задуман как запускалка других программ. У тебя ничего хорошего не получится, как хорошо бы ты не знал этот скриптовый язык для запуска программ. И при этом ты не знаешь этот скриптовый язык.
Это лишь кусочек большого скрипта с ветвлениями и циклами. Мне нужно запускать один файл и чтобы он выполнял всю работу на серверах, принимал разные решения в зависимости от вводных данных, ошибок, которые меняются после каждого последующего запуска. Поэтому я решил, что будет удобнее записывать данные в простые файлы. И при повторном запуске считывать данные с них и выполнять те или иные действия.
Если подключать БД, то вероятно одним скриптом я уже не справлюсь?
Примерно в этом ключе и думал.
Либо с полученной переменной потом в цикле считать все строки, которые ее содержат.
Не надо строить массивы в баше при обработке реальных данных, ты столкнешься с тем, что у баш нет эффективных по скорости и по потреблению памяти структур данных для работы с такими объемами данными.
Поэтому используй баш как запускалку подходящих для этого программ. Не надо считать математику в баш.
Если ты прям не хочешь использовать для этого спец инструменты, хочешь копаться в текстовых файлах, то
Все промежуточные файлы можно скоратить направив через пайпы следующей команде.
Чувствствуешь, что во всем этом практически не используется баш, тупое использование спец-инструментов, и все это есть закат солнца вручную — имитация субд.
Источник