unix - 文件中所有列的不同计数,计数和值的总和

时间:2011-12-26 10:35:11

标签: linux bash shell unix awk

给出如下文件:

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

预期产出:

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

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

到目前为止

代码(在momemnt它没有返回输出):

    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

1 个答案:

答案 0 :(得分:4)

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

script.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)

        ## 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|

编辑:避免多维数组的解决方法。我用下标数组替换它。它的处理更复杂,但我希望它适用于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

}