Уник по последнему полю, сохраняя последнюю строку, и добавление количества дубликатов.

Вопрос или проблема

Мне нужна помощь в реализации команды awk в bash-скрипте для реализации нижеприведенной логики. Пробовал комбинацию sort/uniq, но безуспешно.

У меня есть длинный список с временной меткой и некоторым числом перед ней, как показано ниже.

[2020-09-15 09:03:21.835335] 1021
[2020-09-15 09:03:21.935335] 1021
[2020-09-15 09:03:22.835335] 1022
[2020-09-15 09:03:25.835335] 1022
[2020-09-15 09:04:21.835335] 1023
[2020-09-15 09:05:21.835335] 1023
[2020-09-15 09:04:22.835335] 1023
[2020-09-15 09:05:23.835335] 1023

В конечном итоге я хочу обработать список по отношению ко второму столбцу с числами. В конечных обработанных данных я хотел бы иметь количество уникальных чисел (даже если они встречаются только один раз) из второго столбца и добавить его в новый столбец перед числом. Мне действительно нужно было иметь временную метку с последнего вхождения дубликатов/уникальных записей из столбца с числами.

[2020-09-15 09:03:21.935335] 1021 2
[2020-09-15 09:03:25.835335] 1022 2
[2020-09-15 09:05:23.835335] 1023 4

tac file | uniq -c -f 2 | awk '{$(NF+1)=$1;$1=""}1' | tac

tac выводит файл в обратном порядке. Это необходимо, чтобы гарантировать, что будет сохранено последнее вхождение дублированных строк.

uniq -c -f 2 сравнивает только последнее поле, пропуская первые два с помощью -f 2. Оно добавляет количество дублированных строк с флагом -c, поэтому мы должны перенести это количество в последнее поле. Это делает команда awk '{$(NF+1)=$1;$1=""}1'.

Наконец, tac возвращает все в нужном порядке.

 [2020-09-15 09:03:21.935335] 1021 2
 [2020-09-15 09:03:25.835335] 1022 2
 [2020-09-15 09:05:23.835335] 1023 4

$ awk '
    { map[$3]=$1" "$2; cnt[$3]++ }
    END { for (key in map) print map[key], key, cnt[key] }
' file
[2020-09-15 09:03:21.935335] 1021 2
[2020-09-15 09:03:25.835335] 1022 2
[2020-09-15 09:05:23.835335] 1023 4

Вышеупомянутое выведет строки в случайном порядке, если нужно сохранить порядок из входных данных, это небольшая настройка, например:

$ awk '
    !($3 in map) { keys[++k] = $3 }
    { map[$3]=$1" "$2; cnt[$3]++ }
    END { for (i=1;i<=k;i++) {key=keys[i]; print map[key], key, cnt[key]} }
' file
[2020-09-15 09:03:21.935335] 1021 2
[2020-09-15 09:03:25.835335] 1022 2
[2020-09-15 09:05:23.835335] 1023 4

Ответ или решение

Вопрос, заданный в контексте, касается необходимости обработки текстового файла с временными метками и числовыми значениями за помощью инструментов командной строки Linux, таких как awk, sort, и uniq. Основной целью является создание нового файла, в котором каждая уникальная строка по последнему числовому столбцу сопровождается числом повторений этой строки и временной меткой последнего вхождения.

Теория

В Unix-подобных системах и в особенности в Linux, awk является мощным инструментом для анализа и обработки текстовых данных. Этот инструмент может использоваться для фильтрации текста, сопоставления шаблонов, обработки данных по столбцам и многого другого. Совместно с другими утилитами, такими как sort и uniq, можно выполнять сложную обработку данных, прямо в командной строке.

  1. tac: Эта команда используется для вывода содержимого файла в обратном порядке. Она полезна, когда необходимо работать с последними вхождениями строк в файле, как в нашем случае.

  2. uniq: Эта команда полезна для нахождения и обработки уникальных строк в файле. В контексте текущей задачи uniq используется в сочетании с флагом -c для подсчёта количества повторений, и флагом -f для игнорирования первых полей при сравнении строк.

  3. awk: Записи обрабатываются в awk с использованием простой, но мощной системы сопоставления шаблонов и действий. Он обрабатывает каждую строку, разделяя её на поля и предоставляя гибкие возможности для манипуляции данными внутри строк.

Пример

Для наглядности рассмотрим пример. У вас есть файл с данными приведенного ниже формата:

[2020-09-15 09:03:21.835335] 1021
[2020-09-15 09:03:21.935335] 1021
[2020-09-15 09:03:22.835335] 1022
[2020-09-15 09:03:25.835335] 1022
[2020-09-15 09:04:21.835335] 1023
[2020-09-15 09:05:21.835335] 1023
[2020-09-15 09:04:22.835335] 1023
[2020-09-15 09:05:23.835335] 1023

Цель: получить файл формата, где каждая уникальная строка идентифицируется по последнему числовому полю, имеет временную метку последнего вхождения и количество повторений:

[2020-09-15 09:03:21.935335] 1021 2
[2020-09-15 09:03:25.835335] 1022 2
[2020-09-15 09:05:23.835335] 1023 4

Применение

Для достижения этой цели можно воспользоваться несколькими подходами. Рассмотрим один из них, использующий awk в сочетании с tac и uniq.

tac file.txt | uniq -c -f 2 | awk '{$(NF+1)=$1;$1=""}1' | tac
  1. Использование tac для обращения порядка строк в файле. Это позволит нам начать обработку с последнего вхождения каждого числа, чтобы сохранить последнюю временную метку.

  2. Применение uniq -c -f 2: Эта комбинация позволяет игнорировать первые два поля (временная метка) и сосредоточиться только на уникальности числового поля. Флаг -c добавляет количество повторений каждой строки в начало.

  3. awk для пост-обработки: awk '{$(NF+1)=$1;$1=""}1' перемещает количество повторений из начала строки в конец, оставляя строку с числовым полем и временной меткой.

  4. Финальное tac возвращает строки в их изначальный порядок после обработки.

Альтернативный метод с использованием только awk:

awk '
    { map[$3]=$1" "$2; cnt[$3]++ }
    END { for (key in map) print map[key], key, cnt[key] }
' file.txt

Этот скрипт использует ассоциативные массивы для хранения последней временной метки каждого уникального числа и подсчитывает их количество.

Заключение

Использование утилит командной строки, таких как awk, uniq, и tac, позволяет эффективно обрабатывать текстовые данные без необходимости обращаться к сложным программным языкам. Эти инструменты обеспечивают мощную функциональность и гибкость в манипуляции данными, что делает их незаменимыми для системных администраторов и разработчиков, работающих с большими объемами данных в текстовом формате. Освоение их синтаксиса и возможностей существенно упрощает выполнение рутинных задач по обработке данных в Linux и Unix-системах.

Оцените материал
Добавить комментарий

Капча загружается...