假设目录包含 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