如何计算多个浮点列总和

如何计算多个浮点列总和

我有一个场景,我想计算包含浮点数据的多个列的总和。

我的下面的代码适用于整数值,但不适用于浮动油漆值。

代码非常适合此数据

ID|NAME|SAL|COST|PER|TAG

1|A|10|10|20|10|

1|B|10|15|20|10|

1|C|10|17|25|80|

1|D|115|110|20|100|

1|E|10|10|10|10|

代码 :

#!/bin/bash
FILE="$1"
COLUMNS="${@:2}"
for col in $COLUMNS; do
  colnum=$(awk -v RS='|' '/'$col'/{ print NR; exit}' $FILE)
  awk '{FS="|"}{s+='$colnum'}END{print "'$col' ", s}' $FILE
done | column -t

如何使用上面的代码获得以下数据的总和?

ID|NAME|SAL|COST|PER|TAG

    1|A|9.234|123.12|20.123|67.1|

    1|B|10.12|153.234|20.90|190.34|

    1|C|8.234|17.01|25.777|80.09|

    1|D|11.2|11.222|10.1|10.00000|

    1|E|16.23|10.1|145.22|11.77278|

新代码不起作用:

#!/bin/bash
FILE="$1"
COLUMNS="${@:2}"
for col in $COLUMNS; do
            awk -F'|' '{T+=$col} END { printf "%.10f\n", T }' $FILE
    done | column -t

答案1

首先不要在 shell 中执行此操作,而是在awk. shell 不知道如何进行浮点运算。

您的脚本似乎正在获取一组与要解析的文件名和要考虑的字段名称相对应的参数。

awk与为每列调用两次相比,您可以更有效地执行此操作。

BEGIN { OFS = FS = "|" }

FNR == 1 {
        # Handle the header row. Assuming "cols" is a FS-separated
        # string of column names that we want to sum, pick out the
        # column numbers that we want to process and put them in the
        # array "col". This also converts the "cols" string into a
        # corresponding "header" array.

        nf = split(cols, header)
        for (i = 1; i <= NF; ++i)
                for (j = 1; j <= nf; ++j)
                        if ($i == header[j])
                                col[j] = i
        next
}

{
        # Sum each column that we have enumerated in the "col" array.

        for (i = 1; i <= nf; ++i)
                sum[i] += $(col[i])
}

END {
        # Output a two row table containing only the headers that we
        # have summed over and the accumulated sums.

        $0 = ""

        for (i = 1; i <= nf; ++i)
                $i = header[i]
        print

        for (i = 1; i <= nf; ++i)
                $i = sum[i]
        print
}

使用以下命令在您的第一个文件上运行此命令:

$ awk -v cols="SAL|COST|PER|TAG" -f script.awk file1
SAL|COST|PER|TAG
155|162|95|210

将同一列列出两次会得出两次总和:

$ awk -v cols="SAL|SAL" -f script.awk file1
SAL|SAL
155|155

在第二个文件上:

$ awk -v cols="SAL|COST|PER|TAG" -f script.awk file2
SAL|COST|PER|TAG
55.018|314.686|222.12|359.303

使用后处理column -t

$ awk -v cols="SAL|COST|PER|TAG" -f script.awk file2 | column -s '|' -t
SAL     COST     PER     TAG
55.018  314.686  222.12  359.303

将其放入一个简单的脚本中:

#!/bin/sh

infile=$1
shift

IFS='|'

awk -v cols="$*" -f script.awk "$infile" |
column -s '|' -t

你可以用它作为

$ ./script.sh file1 PER TAG
PER  TAG
95   210

您还可以使用支持 CSV 的工具(例如 CSVkit 中的工具)来为您完成这项工作。

csvstat能够计算 CSV 文件的一些基本“统计数据”。假设您的文件是格式正确的 CSV 文件(它们不是,因为每个数据行都有一个尾随|分隔符),则每列的总和可以通过

$ csvstat --sum file1
  1. ID: None
  2. NAME: None
  3. SAL: 155
  4. COST: 162
  5. PER: 95
  6. TAG: 210
$ csvstat --sum file2
  1. ID: None
  2. NAME: None
  3. SAL: 55.018
  4. COST: 314.686
  5. PER: 222.12
  6. TAG: 359.30278

或者,仅针对单个列:

$ csvstat --sum -c 'SAL' file2
55.018

答案2

我的解决方案将发挥作用

对于此数据集 1 - 对此进行测试

ID|NAME|SAL|COST|PER|TAG
1"|"A"|"50.1123"|"10.1"|"25.22"|"10.2"|"
2"|"B"|"50.11"|"15.45"|"25.1"|"10.1118"|"

对于此数据集 2 - 对此进行测试

ID|NAME|SAL|COST|PER|TAG
1|A|9.234|123.12|20.123|67.1
2|B|10.12|153.234|20.90|190.34
3|C|8.234|17.01|25.777|80.09
4|D|11.2|11.222|10.1|10.00000
5|E|16.23|10.1|145.22|11.77278

有效的解决方案

FILE_NAME="$1"
COLUMN_NAME="$2"

alpha=( $(awk -F"|" 'NR==1{for(i=1;i<=NF;i++){if ($i ~ /'$COLUMN_NAME'/){print i;}}}' $FILE_NAME) )

for each in "${alpha[@]}"
do
      #echo "$each"
      awk -F'"?\\|"?' '{T+=$('$each')} END { printf "%.4f\n", T }' $FILE_NAME
done

像这样跑

bash script.sh DEMO.txt 'SAL|COST|PER|TAG'

输出1:

100.2223
25.5500
50.3200
20.3118

输出2:

55.0180
314.6860
222.1200
359.3028

相关内容