首页 > 解决方案 > 如何添加各种 .csv 文件的所有列的值,仅保持单个标题和第一个标签列相同?

问题描述

所以我在一个结构相同的目录中有各种 .csv 文件,第一行作为标题,第一列作为标签。说文件1如下:

name,value1,value2,value3,value4,......
name1,100,200,0,0,...
name2,101,201,0,0,...
name3,102,202,0,0,...
name4,103,203,0,0,...
....

文件2:

name,value1,value2,value3,value4,......
name1,1000,2000,0,0,...
name2,1001,2001,0,0,...
name3,1002,2002,0,0,...
name4,1003,2003,0,0,...
....

所有 .csv 文件都具有相同的结构,具有相同的行数和列数。

我想要的是看起来像这样的东西:

name,value1,value2,value3,value4,......
name1,1100,2200,0,0,...
name2,1102,2202,0,0,...
name3,1104,2204,0,0,...
name4,1103,2206,0,0,...
....

最后一个文件中的所有值列将是所有 .csv 文件的这些列中相应值的总和。所以在结果文件中的 value1 下我应该有 1000+100+...+... 等等。

.csv 文件的数量不固定,所以我想我需要一个循环。

如何在 Linux 机器上使用 bash 脚本来实现这一点。谢谢!

标签: linuxbashcsv

解决方案


使用AWK,尝试类似:

awk '
    BEGIN {FS=OFS=","}
    FNR==1 {header=$0}      # header line
    FNR>1 {
        sum[FNR,1] = $1     # name column
        for (j=2; j<=NF; j++) {
            sum[FNR,j] += $j
        }
    }
    END {
        print header
        for (i=2; i<=FNR; i++) {
            for (j=1; j<=NF; j++) {
                $j = sum[i,j]
            }
            print
        }
    }' *.csv
  • 它遍历行和列,将值累积到模拟的二维数组sum中。
  • 您不必显式循环遍历 csv 文件。AWK 会自动为您完成。
  • 在读取所有 csv 文件后,它会报告块中每一行和每一列的数量END
  • 请注意,gawk 4.0 及更新版本支持真正的多维数组。

希望这可以帮助。

编辑

为了计算平均值而不是总和,请尝试:

awk '
    BEGIN {FS=OFS=","}
    FNR==1 {header=$0}      # header line
    FNR>1 {
        sum[FNR,1] = $1     # names column
        for (j=2; j<=NF; j++) {
            sum[FNR,j] += $j
        }
    }
    END {
        print header
        files = ARGC - 1    # number of csv files
        for (i=2; i<=FNR; i++) {
            $1 = sum[i,1]   # another treatment for the 1st column
            for (j=2; j<=NF; j++) {
                $j = sum[i,j] / files
                # if you want to specify the number of decimal places,
                # try something like:
                # $j = sprintf("%.2f", sum[i,j] / files)
            }
            print
        }
    }' *.csv

推荐阅读