按列合并目录中的所有 csv 文件

按列合并目录中的所有 csv 文件

假设目录包含 3 个 csv 文件:

第一个 csv:

Name, John
Age, 18

第二个 csv:

Name, Jim
Age, 21

第三个csv:

Name, Amy
Age, 22

我希望结果是:

Name, John, Jim, Amy
Age, 18, 21, 22

重要的是要知道该目录可能有 n 个 csv 我有 bash 和 posix shell 可用

编辑:

这感觉应该可以工作,但在顺序方面仍然存在问题:

awk -F, -v OFS="," '{a[FNR]=a[FNR]?a[FNR]FS$2:$1FS$2}END{for(x in a)print x,a[x]}' *.csv > results.csv

这没有任何意义,因为 FNR 1 应该位于数组中的第一个,但它最后打印?

答案1

你的尝试非常接近。以下是一些修改,以使其按要求工作:

awk -F, -v OFS="," '{
        a[FNR] = (FNR==NR ? $0 : a[FNR] OFS $2)
    }
    END { 
        for(i=1;i<=FNR;i++) print a[i]
    }' *.csv

for (x in a)不保证数组访问顺序,因此为了保持顺序,我们在循环中运行数字索引for。我们也可以使用for (i=1;i<=length(a);i++),但很高兴知道将数组作为参数传递给 并不是length()所有 awks 的标准,您可以在GNU awk 手册

也可以看看:扫描数组

此外,我们使用条件语句FNR==NR,这是“解析第一个文件时”的惯用语,并且想要保存整行$0,对于下一个文件,我们只需附加第二个字段。

答案2

您的数据看起来像是转置表格格​​式(“xtab”),但键值对的分隔符是逗号而不是制表符,并且添加了过多的空格。

为了清理数据并将其转换为 CSV,我们可以使用 Miller ( mlr):

$ mlr --ixtab --ips , --ocsv clean-whitespace fileA fileB fileC
Name,Age
John,18
Jim,21
Amy,22

设置--ips“对分隔符”,即键和值之间使用的分隔符。

datamash假设字段不包含嵌入的逗号或换行符,那么这是最容易用 GNU 转置的:

$ mlr --ixtab --ips , --ocsv clean-whitespace fileA fileB fileC | datamash -t, transpose
Name,John,Jim,Amy
Age,18,21,22

如果输入字段包含逗号,我们可以指定另一个输出字段分隔符(数据中没有出现的分隔符),然后指示datamash使用它:

$ mlr --ixtab --ips , --ocsv --ofs pipe clean-whitespace fileA fileB fileC | datamash -t '|' transpose
Name|John, the dapper|Jim, the mighty|Amy, the awesome
Age|18|21|22

相关内容