我有两个大型 csv 文件,它们共享相同的第一列和第一行(标题),如下所示:等意味着具有相同模式的更多值。
文件1.csv
names,text1,text2,text3,etc
A,1,4,3 ...
B,5,2,8 ...
C,3,7,4 ...
D,9,1,3 ...
etc
文件2.csv
names,text1,test2,text3,etc
A,7,2,9 ...
B,3,0,6 ...
C,8,7,2 ...
D,1,5,6 ...
etc
我想要一个代码/脚本来组合 file1.csv 和 file2.csv 中的列(带有匹配的标题或列 #)以及 file1.csv 中的第一列,并将它们输出到根据标题命名的新文件中。
所以它会给出以下输出文件等等:
文本1.csv
names,text1,text1
A,1,7
B,5,3
C,3,8
D,9,1
etc
文本2.csv
names,text2,text2
A,4,2
B,2,0
C,7,7
D,1,5
etc
文本3.csv
names,text3,text3
A,3,9
B,8,6
C,4,2
D,3,6
etc
答案1
答案2
这类似于米格尔斯维埃拉的回答,但使用 Bash 来计算列数并获取标题:
IFS=, read -a headers < file1.csv
column=0
for h in "${headers[@]}"
do
if [ "$((++column))" = 1 ]
then
continue
fi
join -t, -o "0,1.$column,2.$column" file1.csv file2.csv > "$h".csv
done
输出:
文本1.csv
names,text1,text1
A,1,7
B,5,3
C,3,8
D,9,1
文本2.csv
names,text2,test2
A,4,2
B,2,0
C,7,7
D,1,5
文本3.csv
names,text3,text3
A,3,9
B,8,6
C,4,2
D,3,6
笔记:
read -a
将文件的第一行读入数组。- 该
column
变量的值为 1, 2, 3, 4, ... 当column
为 1 时不进行处理,因为我们不想创建names.csv
输出文件。 - 对于数据列,运行
join
,连接第一列(默认),输出该列和column
每个文件中的数字列。这部分几乎与米格尔斯维埃拉的回答。 - 使用
headers
数组(即第一行的字段file1.csv
)来命名输出文件。
与米格尔斯维埃拉的回答和鲁迪克的回答,这假设
- 这些文件具有相同的列数(理想情况下,它们应该匹配)
- 这些文件具有相同的行数(行)(它们也应该匹配)
如果文件已排序,则效果最好(但如果未排序,则可能会起作用,前提是它们是在里面相同的命令)。再次强调,这必须在 Bash 中完成。
答案3
也试试
join -t, --header file[12] | awk -F, -vOFS=, '
{D = (NF-1)/2
for (i=2; i<=D+1; i++) {if (FNR==1) FN[i] = $i
print $1, $i, $(i+D) > FN[i] ".csv"
}
}
'
cf te*
---------- text1.csv: ----------
names,text1,text1
A,1,7
B,5,3
C,3,8
D,9,1
---------- text2.csv: ----------
names,text2,test2
A,4,2
B,2,0
C,7,7
D,1,5
---------- text3.csv: ----------
names,text3,text3
A,3 ...,9 ...
B,8 ...,6 ...
C,4 ...,2 ...
D,3 ...,6 ...
这取决于具有相同行数和字段数的输入文件,因此join
可以正确完成其部分(假设它提供了--header
选项),并且awk
可以计算迭代次数。然后只需循环遍历这些字段并将它们打印到相关文件中,这些文件的名称已在第一行中捕获。
答案4
awk -F "," 'NR==FNR{a[FNR]=$2;b[$1]++;next}($1 in b){print $1,a[FNR],$2}' file1 file2
输出
file1
names text1 text1
A 1 7
B 5 3
C 3 8
D 9 1
awk -F "," 'NR==FNR{a[FNR]=$3;b[$1]++;next}($1 in b){print $1,a[FNR],$3}' file1 file2
输出
file2
names text2 test2
A 4 2
B 2 0
C 7 7
D 1 5
awk -F "," 'NR==FNR{a[FNR]=$4;b[$1]++;next}($1 in b){print $1,a[FNR],$4}' file1 file2
输出
file3
names text3 text3
A 3 9
B 8 6
C 4 2
D 3 6