Хобрук: Ваш путь к мастерству в программировании

Суммируйте значения в повторяющихся строках с помощью Bash

Я видел разные версии этого вопроса в Stack Overflow, но не встречал ни одной, которая касается этого конкретного варианта использования.

Цель

Поиск повторяющихся строк на основе всей строки (а не только одного столбца), кроме значения в последнем столбце. Удалите все повторяющиеся строки, кроме одной, но сначала просуммируйте значения в последнем столбце каждого дубликата и покажите полученное значение в последнем столбце оставшейся повторяющейся строки. Я хотел бы сделать это в Bash.

Вариант использования

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

Пример

Исходный файл:

url,title,tag,version,guide,views
"https://website.com/1-1/section/product/page-title","Page Title 1",tag-1,"1-1","guide-1",100
"https://website.com/2-2/section/product/page-title","Page Title 2",tag-2,"2-2","guide-2",5
"https://website.com/1-1/section/product/page-title","Page Title 1",tag-1,"1-1","guide-1",15
"https://website.com/3-3/section/product/page-title","Page Title 3",tag-3,"3-3","guide-3",10
"https://website.com/3-3/section/product/page-title","Page Title 3",tag-3,"3-3","guide-3",20
"https://website.com/4-4/section/product/page-title","Page Title 4",tag-4,"4-4","guide-4",7
"https://website.com/3-3/section/product/page-title","Page Title 3",tag-3,"3-3","guide-3",30

Желаемый файл:

url,title,tag,version,guide,views
"https://website.com/1-1/section/product/page-title","Page Title 1",tag-1,"1-1","guide-1",115
"https://website.com/2-2/section/product/page-title","Page Title 2",tag-2,"2-2","guide-2",5
"https://website.com/3-3/section/product/page-title","Page Title 3",tag-3,"3-3","guide-3",60
"https://website.com/4-4/section/product/page-title","Page Title 4",tag-4,"4-4","guide-4",7

Что я хотел бы сделать здесь, так это поделиться каждой итерацией сценария, которую я пробовал, и разобрать, что сработало, а что нет. Это настолько выше моей головы, что я изо всех сил пытаюсь сделать даже это. Мой процесс заключался в том, чтобы использовать части ответов на аналогичные вопросы о переполнении стека (все они были в awk, что имеет смысл для меня) и изменить сравниваемый столбец. Но поскольку некоторые ответы сравнивают только один столбец, результаты моих изменений противоречивы и странны. Сценарии достаточно сложны, и я изо всех сил пытаюсь понять, почему.

Кто-нибудь может дать образование о том, как я могу найти ответ, или пример, который указывает мне правильное направление? Спасибо, если так.

awk
20.06.2020

  • Может ли "Page Title 1" включать запятую? Непонятно, почему это невозможно, и это серьезно повлияет на возможные решения.... 20.06.2020

Ответы:


1

Это будет работать независимо от того, может ли какое-либо из полей в кавычках содержать , (например, если какое-либо из полей с текстом-заполнителем "Page Title 1" на самом деле было чем-то вроде "I, Robot - Page 1"):

$ awk '
    BEGIN { FS=OFS="," }
    NR==1 { print; next }
    { num=$NF; sub(/,[^,]*$/,""); sum[$0]+=num }
    END { for (key in sum) print key, sum[key] }
' file
url,title,tag,version,guide,views
"https://website.com/2-2/section/product/page-title","Page Title 2",tag-2,"2-2","guide-2",5
"https://website.com/4-4/section/product/page-title","Page Title 4",tag-4,"4-4","guide-4",7
"https://website.com/1-1/section/product/page-title","Page Title 1",tag-1,"1-1","guide-1",115
"https://website.com/3-3/section/product/page-title","Page Title 3",tag-3,"3-3","guide-3",60
20.06.2020

2

Один из способов использования GNU datamash:

$ echo "url,title,tag,version,guide,views" && datamash --header-in -st, -g1,2,3,4,5 sum 6 < input.txt
url,title,tag,version,guide,views
"https://website.com/1-1/section/product/page-title","Page Title 1",tag-1,"1-1","guide-1",115
"https://website.com/2-2/section/product/page-title","Page Title 2",tag-2,"2-2","guide-2",5
"https://website.com/3-3/section/product/page-title","Page Title 3",tag-3,"3-3","guide-3",60
"https://website.com/4-4/section/product/page-title","Page Title 4",tag-4,"4-4","guide-4",7

Или с awk:

$ awk -F, 'NR==1 { print; next }
           { groups[$1 "," $2 "," $3 "," $4 "," $5] += $6 }
           END { PROCINFO["sorted_in"] = "@ind_str_asc" # Sorted output when using GNU awk
                 for (g in groups) print g "," groups[g]
           }' input.txt
url,title,tag,version,guide,views
"https://website.com/1-1/section/product/page-title","Page Title 1",tag-1,"1-1","guide-1",115
"https://website.com/2-2/section/product/page-title","Page Title 2",tag-2,"2-2","guide-2",5
"https://website.com/3-3/section/product/page-title","Page Title 3",tag-3,"3-3","guide-3",60
"https://website.com/4-4/section/product/page-title","Page Title 4",tag-4,"4-4","guide-4",7
20.06.2020
  • вы можете сэкономить несколько нажатий клавиш, заменив "," на FS, что более важно, единую точку изменения в случае другого разделителя. 20.06.2020

  • 3

    другой awk

    $ awk -F, -v OFS=, 'NR==1 {print; next} 
                              {v=$NF; NF--; a[$0]+=v} 
                        END   {for(k in a) print k,a[k] | "sort"}' file
    
    url,title,tag,version,guide,views
    "https://website.com/1-1/section/product/page-title","Page Title 1",tag-1,"1-1","guide-1",115
    "https://website.com/2-2/section/product/page-title","Page Title 2",tag-2,"2-2","guide-2",5
    "https://website.com/3-3/section/product/page-title","Page Title 3",tag-3,"3-3","guide-3",60
    "https://website.com/4-4/section/product/page-title","Page Title 4",tag-4,"4-4","guide-4",7
    

    Пояснение
    вывести строку заголовка; сохраните значение (последнее поле), уменьшите количество полей, чтобы оставшаяся часть записи стала ключом ($0), добавьте значение в аккумулятор с ключом (суммирует эквивалентные значения ключа). В конце выведите ключ и значения и отсортируйте.

    20.06.2020
    Новые материалы

    Декларативное и функциональное программирование в стиле LINQ с использованием JavaScript с использованием каррирования и генератора ...
    LINQ - одна из лучших функций C #, которая обеспечивает элегантный способ написания кода декларативного и функционального стиля, который легко читать и понимать. Благодаря таким функциям ES6,..

    Структуры данных в C ++ - Часть 1
    Реализация общих структур данных в C ++ C ++ - это расширение языка программирования C, которое поддерживает создание классов, поэтому оно известно как C с классами . Он используется для..

    Как я опубликовал свое первое приложение в App Store в 13 лет
    Как все началось Все началось три года назад летом после моего четвертого класса в начальной школе. Для меня, четвертого класса, лето кажется бесконечным, пока оно не закончится, и мой отец..

    Что в лицо
    Очерк о возвращении физиогномики и о том, почему мы должны это приветствовать. История начинается со странной науки. Р. Тора Бьорнсдоттир, Николас О. Рул. Видимость социального класса по..

    Почему шаблоны проектирования и почему нет?
    Сложность — мать всех проблем в программировании. Программное обеспечение должно быть разработано с точки зрения того, кто его поддерживает, а не того, кто его пишет, потому что программное..

    Создание дизайна обуви с помощью машинного обучения
    Обувь. Что подождать? Я думал, что речь пойдет о машинном обучении! Ну это так. Если бы вы пошли на Amazon, сколько обуви вы бы нашли? Наверное, много, не так ли? Но много ли в них..

    GraalVM в 2022 году: итоги года
    2022 год был очень продуктивным для проекта и сообщества GraalVM. Вместе мы разработали множество новых функций, выпустили GraalVM для последних версий Java и новых платформ и увидели несколько..