создайте сумму вложенных категорий с помощью awk

#unix #reporting #awk

#unix #создание отчетов #awk

Вопрос:

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

 2011-02-01,-4.00,entertainment/itunes
2011-02-02,-5.00,entertainment/food/dinner
2011-02-03,-6.00,entertainment/food/take-away/thai
2011-02-04,-7.00,entertainment/food/take-away/indian
2011-02-05,-8.00,entertainment/books/kindle
2011-02-05,-8.00,entertainment/books/kindle
2011-02-06,-9.00,entertainment/books/real
  

Я хотел бы использовать awk для создания отчета, суммирующего каждый узел в дереве категорий.

например

 entertainment:-47.00
entertainment/books:-25.00
entertainment/books/kindle:-16.00
entertainment/books/real:-9.00
entertainment/food:-18.00
entertainment/food/take-away:-13.00
entertainment/food/take-away/indian:-7.00
entertainment/food/take-away/thai:-6.00
  

Буду признателен за любую помощь.

Комментарии:

1. Это был вопрос с подвохом: посмотрим, удалим ли мы расходы itunes?

Ответ №1:

Как это?

 awk -F, '{
     tots["/"$3] =$2
     n=split($3, tmpT, "/")
     key="/"
     for (i=1;i<n;i  ) {
         key  = ( key == "/" ) ? key tmpT[i]  : key "/"  tmpT[i]
         tots[key] =$2
     }
 }
 END{
     for (t in tots) print t "t" tots[t]
 }' testData.txt | sort -u

**Output**
/entertainment  -47       
/entertainment/books    -25
/entertainment/books/kindle     -16
/entertainment/books/real       -9
/entertainment/food     -18
/entertainment/food/dinner      -5
/entertainment/food/take-away   -13
/entertainment/food/take-away/indian    -7
/entertainment/food/take-away/thai      -6
/entertainment/itunes   -4
  

Для каждого подузла она суммируется.

Не уверен, что это критическая часть.

Я надеюсь, что это поможет.

Комментарии:

1. Идеально, именно то, что я искал.

Ответ №2:

Ну, я не использую awk, но, возможно, это помогло бы:

 cat input |
  perl -e 'while (<>) 
     { chomp; (undef, $bal, $cat) = split /,/; $tot{$cat}  = 1.0 * $bal   0.0; } 
     map { print "$_: $tot{$_}n" } keys %tot; '
  

Ха, это заняло некоторое время (жизнь продолжается), но я вижу, что никто не опередил меня в этом?! Больше не могу оправдать использование этого oneliner…:

 #!/usr/bin/perl
use strict;
use warnings;

my %tot;

while (<>) 
{ 
    chomp; 
    my (undef, $bal, $cat) = split /,/; 
    my @subs = split (qr(/), $cat);

    $tot{$_}  = ($bal 0.0) 
        foreach (map { join('/', @subs[0..$_]) } (0 .. $#subs))
} 

map { print "$_: $tot{$_}n" } sort keys %tot;
  

Ответ №3:

Сделайте это в командной строке: скрипт не нужен.Просто давайте сохраним это простым и понятными

 awk -F",|/" '{a[$3] =$2;
              b[$3"/"$4] =$2;
              c[$3"/"$4"/"$5] =$2;
              d[$3"/"$4"/"$5"/"$6] =$2}
          END{for (i in a) print i","a[i];
              for (j in b) print j","b[j];
              for (k in c) print k","c[k];
              for (l in d) print l","d[l];}' file.txt|grep -v '/,'
  

вывод:

 entertainment,-47
entertainment/books,-25
entertainment/itunes,-4
entertainment/food,-18
entertainment/books/kindle,-16
entertainment/books/real,-9
entertainment/food/take-away,-13
entertainment/food/dinner,-5
entertainment/food/take-away/thai,-6
entertainment/food/take-away/indian,-7