2011-12-26 48 views
0

所有列值的总和给出一个文件如:UNIX - 重复计数,计数和文件

sid|storeNo|latitude|longitude 
2|1|-28.03720000 
9|2 
10 
jgn352|1|-28.03720000 
9|2|fdjkjhn422-405 
|gfdjk39 

预期输出:

sid|storeNo|latitude|longitude 
543240|6|-56.0744|0| 
6|5|3|0| 
5|3|2|0| 

我想返回值的计数在每列下,每列下不同值的计数,然后是每列下所有值的总和。但是,我的逻辑/语法肯定是错的,任何帮助纠正它都会很棒!

代码到目前为止(在momemnt它返回无输出):使用gawk

awk 'BEGIN{FS="|"} 
    NR==1{ 
      for(n = 1; n <= NF; n++) { 
       colname[n]=$n 
      } 
     } 
    NR>1 { #skips header 
    for(j=1;j<=NF;j++) 
    { 
     sum[j]+=$j 
     rawcount[j]++ 
     #distinctcount[j, arr[j]]=1 
    } 
    } 
    END{ 
    for(k=1;k<=NF;k++) 
    { 
    #for(i in distinctcount) 
    # distinctcount[k, i]++ 
    print colname[j]"|" 
print sum[j]"|" 
print rawcount[j]"|" 
print distinctcount[j]"|" 
    } 
    }' delimd2iffpipe.dat 
+0

你用各种脚本所做的所有事情最好用数据库完成(例如sqlite,很容易编写脚本)。 “总和”与您的样本没有很好的定义 - 您如何处理不是数字的条目?是否存在不存在的细胞?如果是这样,他们所有不同或将3个空细胞计为1在你的不同计数,或0? – Mat 2011-12-26 10:41:33

+0

@Mat -Sum将只添加数值,如果一个值中有任何非数字字符,那么它将不会被包含在总和中。不存在的细胞不计算在内。即在不同的计数中为0,因为它没有值。 – toop 2011-12-26 10:46:37

+0

你为什么试图用文本文件和bash脚本来做到这一点?这绝对是使用DB后端(Mat推荐的sqlite或MySQL)和使用Python或Perl等编程语言来处理更好的方法。 – Drahkar 2011-12-26 10:49:18

回答

4

一种可能的解决方案。 该脚本使用多维数组,我认为它只支持GNU版本。

BEGIN { 
     FS="|" 
} 

## Header. 
NR==1{ 
     ## Get this number to know later how many columns to print. 
     cols = NF; 

     ## Print header. 
     print 

     ## Read next record. 
     next 
} 

## Data. 
NR>1 { 
    ## For each column, get sum, count and distinct count, save values in arrays. 
    for(j=1;j<=NF;j++) 
    { 
     sum[j] += $j 
     rawcount[j]++ 
     distcount[j][$j]++ 
    } 
} 

END{ 
     print_line(sum) 
     print_line(rawcount) 

     ## To print distinct count, for each column we count how many values exist in 
     ## second dimension. 
     for (i = 1; i <= cols; i++) { 
       printf "%g|", length(distcount[i]) ? length(distcount[i]) : 0 
     } 
     print 
} 

func print_line(arr) 
{ 
     for (k = 1; k <= cols; k++) { 
       printf "%g|", arr[k] ? arr[k] : 0 
     } 
     print 

} 

运行脚本:

awk -f script.awk delimd2iffpipe.dat 

结果:

sid|storeNo|latitude|longitude 
543240|6|-56.0744|0| 
6|5|3|0| 
5|3|2|0| 

内容script.awk(含评论)的编辑:避免多维数组的方法。我用一个下标数组替代它。它的处理更复杂,但我希望它可以与所有版本的awk

这里的代码。我的机器中的结果与以前的脚本相同。

BEGIN { 
     FS="|" 
} 

## Header. 
NR==1{ 
     ## Get this number to know later how many columns to print. 
     cols = NF; 

     ## Print header. 
     print 

     ## Read next record. 
     next 
} 

## Data. 
NR>1 { 
     ## For each column, get sum, count and distinct count, save values in arrays. 
    for(j=1;j<=NF;j++) 
    { 
     sum[j] += $j 
     rawcount[j]++ 
     distcount[j, $j]++ 
    } 
} 

END{ 
     print_line(sum) 
     print_line(rawcount) 

     for (combined_index in distcount) { 
       split(combined_index, idx, SUBSEP) 
       dcount[ idx[1] ]++; 
     } 
     print_line(dcount) 
} 

func print_line(arr) 
{ 
     for (k = 1; k <= cols; k++) { 
       printf "%g|", arr[k] ? arr[k] : 0 
     } 
     print 

} 
+0

line:23:distcount [j] [$ j] ++ ^语法错误 – toop 2011-12-26 13:12:26

+0

@toop:增加了一个'awk'脚本,用下标数组代替'gawk'特定的多维数组。我希望它适用于您的版本。 – Birei 2011-12-26 13:54:09

+0

传说!它不适用于我的awk,但适用于nawk。 – toop 2011-12-26 23:11:08