Проблема
У меня есть файл журнала со следующим форматом:
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 используется каким-либо другим способом, чем, я использовал его), спасибо.
Любая справка очень ценится.
С плоскостью 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 с тем разделителем.