Конвертировать плоский файл в другой формат, используя оболочку или Python - PullRequest
0 голосов
/ 01 мая 2018

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

User: user1
Count:3
Sum:80
  departmentId: dept1
  Amount by departmentId: 20
  departmentId: dept1
  Amount by departmentId: 35
  departmentId: dept2
  Amount by departmentId: 25
User: user2
Count:3
Sum:7.199999999999999
  departmentId: dept1
  Amount by departmentId: 2.4
  departmentId: dept2
  Amount by departmentId: 2.4
  departmentId: dept3
  Amount by departmentId: 2.4
User: user3
Count:1
Sum:0.2
  departmentId: dept2
  Amount by departmentId: 0.2
User: user4
Count:2
Sum:2
  departmentId: dept3
  Amount by departmentId: 1
  departmentId: dept3
  Amount by departmentId: 1

Список файлов в основном Пользовательский сбор за отдел. Если один и тот же пользователь связан с отделом несколько раз, его необходимо объединить в один ряд. Выходной файл должен быть в следующем формате.

РЕДАКТИРОВАТЬ: Для пользователя 1, он имеет 2 взноса для dept1 и 1 из-за dept2. Таким образом, в выходном файле 2 сбора для dept1 должны быть объединены в 1, и общее количество в строке будет равно 2, так как количество должно быть пользователем на отдел.

Format:
count total_sum
userId+deptId sum for that dept

Example:

2 80
user1dept1 55
user1dept2 25
3 7.2
user2dept1 2.4
user2dept2 2.4
user2dept3 2.4
1 0.2
user3dept2 0.2
1 2
user4dept3 2

Посоветуйте, пожалуйста, какой язык сценариев использовать, bash или python? И как перебрать входной файл? Спасибо

1 Ответ

0 голосов
/ 01 мая 2018

Вы не используете оболочку для манипулирования текстом (см. https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice по некоторым причинам). Awk - это инструмент, который изобрели ребята, которые изобрели оболочку для вызова оболочки для манипулирования текстом, поэтому просто используйте это.

$ cat tst.awk
BEGIN { FS=": *" }
{
    gsub(/^ +| +$/,"")
    f[$1] = $2
}
/Amount/ {
    dept = f["departmentId"]
    subTot[dept] += $2
    tot += $2
}
$1 == "User" {
    if (NR>1) {
        prt()
    }
    user = $2
}
END { prt() }

function prt() {
    print length(subTot), tot
    for (dept in subTot) {
        print user dept, subTot[dept]
    }
    delete subTot
    tot = 0
}

.

$ awk -f tst.awk file
2 80
user1dept1 55
user1dept2 25
3 7.2
user2dept1 2.4
user2dept2 2.4
user2dept3 2.4
1 0.2
user3dept2 0.2
1 2
user4dept3 2

Выше предполагается, что у вас есть awk, где length(array) дает вам количество элементов в массиве. Если вы этого не сделаете, просто подсчитывайте каждый раз, когда вы видите новый отдел для текущего пользователя (например, с помощью if (!(dept in subTot)) numDepts++ непосредственно перед заполнением subTot[dept]), и вместо этого выведите это значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...