Как я получаю список уникальных имен и сумму чисел от каждой строки, содержащей это имя с 1 командой?

Проблема

У меня есть файл журнала со следующим форматом:

2018/12/05 22:43:14 [ChestShop] User bought 1 Boat for 8.00 from Admin Shop at [...] -246, 65, 61
2019/01/02 10:09:38 [ChestShop] User sold 64 Sea Lantern for 27840.00 to Admin Shop at [...] -234, 61, 45
2019/01/02 10:09:38 [ChestShop] User sold 48 Sea Lantern for 20880.00 to Admin Shop at [...] -234, 61, 45
2019/01/02 10:09:42 [ChestShop] User sold 2 Prismarine Bricks for 248.00 to Admin Shop at [...] -233, 62, 45

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

Информацией, которую я хочу суммировать, являются имена, количества, и продайте значения. Продайте значения, общее количество, продают значение за перечисленное количество. Имена (Морской Фонарь, Кирпичи Prismarine и т.д.) могут появиться несколько раз в этом файле журнала наряду с количествами (число слева от имен) и продать значения (число направо от "для". Имена могут содержать несколько пробелов (никогда, чем 4) или ни один вообще.

... ... [...] ... ... 2 Prismarine Bricks ... 248.00 ... ... ... ... [...] ..., ..., ...

Предпочтительно, я хотел бы, чтобы сводка посмотрела что-то как:

totalQuantity1 uniqueName1 totalSellValue1
totalQuantity2 uniqueName2 totalSellValue2

отсортированный по totalQuantity ИЛИ totalSellValue, в зависимости от небольшого изменения команды.

Мой attemps при решении проблемы

Я узнал, что могу использовать следующую команду для получения списка большинства происходящих объектов и суммы времен, они происходят в файле журнала, отсортированном по сумме времен, они происходят (который не является тем, что я хочу):

cat ChestShop.log | grep -w sold | cut -d ' ' -f 7,8,9,10,11 | awk -F 'for' '{print $1}' | sort | uniq -c | sort -rn

grep -w sold команда просто используется для дифференциации покупки у продажи, и как Вы видите от примеров журнала выше только двух слов, отличаются при сравнении покупающий продаже.

Я также использовал эту команду для суммирования количества одного конкретного объекта из списка, содержащего только количества для того объекта:

cat ChestShop.log | grep -w sold | grep -w 'Magma Block' | cut -d ' ' -f 6 | paste -s -d+ - | bc

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

Любая справка очень ценится.

0
задан 3 January 2019 в 11:54

1 ответ

С плоскостью Awk Вы могли сделать что-то вроде этого:

$ awk '$5 == "sold" {
    q[$7 FS $8] += $6; v[$7 FS $8] += $6 * $10
  } 
  END {
    for (item in q) print q[item], item, v[item]
  }' ChestShop.log 
2 Prismarine Bricks 496
112 Sea Lantern 2784000

С GNU Awk (gawk) версия 4.0 +, можно управлять порядком сортировки следующим образом:

gawk '$5 == "sold" {
    q[$7 FS $8] += $6; v[$7 FS $8] += $6 * $10
  } 
  END {
    PROCINFO["sorted_in"] = "@val_num_desc";
    for (item in q) print q[item], item, v[item]
  }' ChestShop.log 

(отсортированный в порядке убывания количества) или

gawk '$5 == "sold" {
    q[$7 FS $8] += $6; v[$7 FS $8] += $6 * $10
  } 
  END {
    PROCINFO["sorted_in"] = "@val_num_asc";
    for (item in v) print q[item], item, v[item]
  }' ChestShop.log 

(отсортированный в порядке возрастания значения). Обратите внимание, что все они предполагают, что формат Вашего файла как первоначально показывают с именем каждого объекта, состоящим из разделенного поля 7-го и 8-го пробела. Если это не будет, то необходимо будет, вероятно, проанализировать его с регулярным выражением и получить элементы - например, с помощью GNU Awk:

gawk 'match($0, /sold ([0-9]+) (.*) for ([0-9.]+)/, m) {
    q[m[2]] += m[1]; v[m[2]] += m[3]
  } 
  END {
    PROCINFO["sorted_in"] = "@val_num_asc";
    for (item in v) print q[item], item, v[item]
  }' ChestShop.log

Обратите внимание, что это предполагает что keyord for не может появиться в другом месте в строке.

Если у Вас нет доступа к GNU Awk, thn это может быть более просто предварительно обработать файл с другим regex инструментом для вставки соответствующих разделителей так, чтобы можно было затем использовать POSIX awk с тем разделителем.

1
ответ дан 26 October 2019 в 16:01

Другие вопросы по тегам:

Похожие вопросы: