组合两个文件中的列并将它们分成单独的输出文件

组合两个文件中的列并将它们分成单独的输出文件

我有两个大型 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

假设两个文件都已排序(不包括标题行),根据您的示例,以下内容应该有效:

column=2
until [[ $column > $(awk -F, '{ print NF; exit }' file1.csv) ]] ; do 
  join -t , -o 1.1,1.$column,2.$column file1.csv file2.csv > $(awk -F, '{ print $'$column'; exit }' file1.csv).csv 
  ((column++))
done

(借用了一个片段@贾诺斯这个回复.)

这里的大部分魔法都是由join;完成的。输出文件将写入当前目录。

答案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

相关内容