我在一个文件夹中有多个大型 csv 文件,我正在尝试将它们绑定(连接)到一个 csv 中。但是,在执行此操作时,我想确保所有列值在连接后都进入适当的列。由于内存限制,我无法在 R 中执行此操作。我对 shell 脚本编写非常陌生,我知道可能有某种方法可以做到这一点,而无需将所有 csv 文件放入内存中。
例如。
> csv1
A B C D E
1 2 4 5 6
4 5 7 8 9
3 5 6 7 8
2 3 4 5 8
> csv1
C B E D A
10 22 43 35 66
14 15 37 48 99
33 25 56 67 88
> Desired Output
A B C D E
1 2 4 5 6
4 5 7 8 9
3 5 6 7 8
2 3 4 5 8
66 22 10 35 43
99 15 14 48 37
88 25 33 67 56
我的尝试:
我尝试在保存时在 R 中为每个文件设置列顺序,然后使用下面的代码进行连接。我想知道一种可以在 linux shell 中完成所有操作的方法。
我的尝试:
nawk 'FNR==1 && NR!=1{next;}{print}' *.csv > result.csv
Any help is highly appreciated.
RavindraSingh13 的解决方案-
awk '
BEGIN{
PROCINFO["sorted_in"] = "@ind_num_asc"
}
FNR==1{
for(i=1;i<=NF;i++){
a[$i]=i};
if(FNR==1 && FNR==NR){
print};
next
}
{
for(j in a){
printf("%s ",$a[j])}
print ""
}
' csv1 csv2
但是,在上面的解决方案中,它在连接时跳过了一些行。
答案1
GNUawk
解决方案。不过,它会映射内存中的所有值。
merge_by_headers.awk
脚本:
#!/bin/awk -f
BEGIN{ PROCINFO["sorted_in"] = "@ind_str_asc" }
NR==1 || FNR==1{
for (i=1; i<=NF; i++) map[i] = $i;
c = NF; next
}
NR==FNR{
row_cnt = NR-1;
for (i=1; i<=NF; i++) a[map[i]][row_cnt] = $i;
next
}
{
row_cnt += 1;
for (i=1; i<=NF; i++) a[map[i]][row_cnt] = $i;
}
END{
delete map; h = "";
for (k in a) h = (h? h OFS:"")k;
print h;
for (i=1; i<=row_cnt; i++) {
cnt = c;
for (k in a) printf "%d%s", a[k][i], (--cnt? OFS : ORS)
}
}
用法:
awk -f merge_by_headers.awk 1.csv 2.csv | column -t
输出:
A B C D E
1 2 4 5 6
4 5 7 8 9
3 5 6 7 8
2 3 4 5 8
66 22 10 35 43
99 15 14 48 37
88 25 33 67 56