AWK比较2个csv文件
AWK to compare 2 csv files
需要帮助来比较 2 个 csv 文件。列数未知。
文件 1
A,B,C,D,E,F,G
1,2,3,4,5,6,7
7,6,5,4,3,2,1
文件 2
A,B,C,D,E,F,G
1,2,3,4,5,5,7
7,6,6,4,3,2,1
期望的输出
Item FILE1 FILE2
1 F=6 F=5
7 C=5 C=6
如果有更多的列不匹配,那么输出应该是这样的。
Item FILE1 FILE2
1 F=6 F=5
--- ---
--- ---
7 C=5 C=6
您可以使用以下命令:
paste -d '\n' file1 file2 | sed '1d' | awk -F',' 'NR==1{print "Item\tFILE1\tFILE2";for(i=1;i<=NF;i++)header[i]=$i;}NR>1{for(i=1;i<=NF;i++)l1[i]=$i;getline;for(i=1;i<=NF;i++)l2[i]=$i;p=1;for(i=1;i<=NF;i++){if(l1[i]!=l2[i])if(p){print l1[1]"\t"header[i]"="l1[i]"\t"header[i]"="l2[i];p=0;}else print " \t---\t---"}}'
文件 1:
A,B,C,D,E,F,G
1,2,3,1,4,6,7
7,6,5,2,3,2,1
文件 2:
A,B,C,D,E,F,G
1,2,3,4,5,5,7
7,6,6,4,3,2,1
说明:
paste -d '\n' file1 file2
将交错 2 个输入文件
输出:(对于我的 2 个输入文件)
A,B,C,D,E,F,G
A,B,C,D,E,F,G
1,2,3,1,4,6,7
1,2,3,4,5,5,7
7,6,5,2,3,2,1
7,6,6,4,3,2,1
sed '1d'
删除双header
awk
会将 header 行保存在 header
数组中;然后每 2 取 2 行并遍历所有字段并将它们保存在 2 个数组 l1
和 l2
中,然后我们逐一比较这 2 个数组的元素,一旦我们得到第一个差异我们打印它,如果我们已经打印了一个差异,那么 p
变成 0
并且我们更改我们打印的输出以遇到新的差异
最终输出:(对于我的 2 个输入文件)
Item FILE1 FILE2
1 D=1 D=4
--- ---
--- ---
7 C=5 C=6
--- ---
awk代码格式为-F',':
NR==1{
print "Item\tFILE1\tFILE2";
for(i=1;i<=NF;i++)header[i]=$i;
}
NR>1{
for(i=1;i<=NF;i++)l1[i]=$i;
getline;
for(i=1;i<=NF;i++)l2[i]=$i;
p=1;
for(i=1;i<=NF;i++){
if(l1[i]!=l2[i])
if(p){
print l1[1]"\t"header[i]"="l1[i]"\t"header[i]"="l2[i];
p=0;
}
else
print " \t---\t---"
}
}
如果你想显示所有差异使用
NR==1{
print "Item\tFILE1\tFILE2";
for(i=1;i<=NF;i++)header[i]=$i;
}
NR>1{
for(i=1;i<=NF;i++)l1[i]=$i;
getline;
for(i=1;i<=NF;i++)l2[i]=$i;
p=1;
for(i=1;i<=NF;i++){
if(l1[i]!=l2[i])
if(p){
print l1[1]"\t"header[i]"="l1[i]"\t"header[i]"="l2[i];
p=0;
}
else
print " \t"header[i]"="l1[i]"\t"header[i]"="l2[i];
}
}
或在一个命令中:
paste -d '\n' file1 file2 | sed '1d' | awk -F',' 'NR==1{print "Item\tFILE1\tFILE2";for(i=1;i<=NF;i++)header[i]=$i;}NR>1{for(i=1;i<=NF;i++)l1[i]=$i;getline;for(i=1;i<=NF;i++)l2[i]=$i;p=1;for(i=1;i<=NF;i++){if(l1[i]!=l2[i])if(p){print l1[1]"\t"header[i]"="l1[i]"\t"header[i]"="l2[i];p=0;}else print " \t"header[i]"="l1[i]"\t"header[i]"="l2[i]; }}'
这会产生以下输出:
Item FILE1 FILE2
1 D=1 D=4
E=4 E=5
F=6 F=5
7 C=5 C=6
D=2 D=4
~> ( nl file1.txt && nl file2.txt ) | sort | awk 'BEGIN{cnt=1;print "Item\tFILE1\tFILE2"}{if (NR==1) split(,col,",");}{if ((NR%2)==1){split(,data_2_NR,",");}else {split(,data_1_NR,","); for (i in data_1_NR) if (data_1_NR[i]!=data_2_NR[i]) print cnt++ "-" data_1_NR[1] "\t"col[i]"="data_1_NR[i] "\t"col[i]"=" data_2_NR[i] }}' }}'
输出:
Item FILE1 FILE2
1-1 F=6 F=5
2-7 C=6 C=5
解释:
为每个文件添加行号并排序结果
( nl file1.txt && nl file2.txt ) | sort | \
输出:
1 A,B,C,D,E,F,G
1 A,B,C,D,E,F,G
2 1,2,3,4,5,5,7
2 1,2,3,4,5,6,7
3 7,6,5,4,3,2,1
3 7,6,6,4,3,2,1
开始计数器 (cnt) 用于差异数和打印 table 标题
awk 'BEGIN{cnt=1;print "Item\tFILE1\tFILE2"}\
从第一行获取列名称(拆分 $2 因为我们需要原始内容而不是编号,编号用于排序)
{if (NR==1) split(,col,",");}\
由于我们已经完成了初始排序,我们可以查看奇数行和偶数行的差异
将奇数行拆分为名为 data_2_NR
的数组
{if ((NR%2)==1){split(,data_2_NR,",");}\
偶数行到名为 data_1_NR
的数组
else {split(,data_1_NR,",");\
运行 data_1_NR & data_2_NR 数组中的所有列并比较每个数组单元格
for (i in data_1_NR) if (data_1_NR[i]!=data_2_NR[i])\
如果它们在 table
中的打印行不同
print cnt++ "-" data_1_NR[1] "\t"col[i]"="data_1_NR[i] "\t"col[i]"=" data_2_NR[i]}}' }}'
输出
Item FILE1 FILE2
1-1 F=6 F=5
2-7 C=6 C=5
需要帮助来比较 2 个 csv 文件。列数未知。
文件 1
A,B,C,D,E,F,G
1,2,3,4,5,6,7
7,6,5,4,3,2,1
文件 2
A,B,C,D,E,F,G
1,2,3,4,5,5,7
7,6,6,4,3,2,1
期望的输出
Item FILE1 FILE2
1 F=6 F=5
7 C=5 C=6
如果有更多的列不匹配,那么输出应该是这样的。
Item FILE1 FILE2
1 F=6 F=5
--- ---
--- ---
7 C=5 C=6
您可以使用以下命令:
paste -d '\n' file1 file2 | sed '1d' | awk -F',' 'NR==1{print "Item\tFILE1\tFILE2";for(i=1;i<=NF;i++)header[i]=$i;}NR>1{for(i=1;i<=NF;i++)l1[i]=$i;getline;for(i=1;i<=NF;i++)l2[i]=$i;p=1;for(i=1;i<=NF;i++){if(l1[i]!=l2[i])if(p){print l1[1]"\t"header[i]"="l1[i]"\t"header[i]"="l2[i];p=0;}else print " \t---\t---"}}'
文件 1:
A,B,C,D,E,F,G
1,2,3,1,4,6,7
7,6,5,2,3,2,1
文件 2:
A,B,C,D,E,F,G
1,2,3,4,5,5,7
7,6,6,4,3,2,1
说明:
paste -d '\n' file1 file2
将交错 2 个输入文件
输出:(对于我的 2 个输入文件)
A,B,C,D,E,F,G
A,B,C,D,E,F,G
1,2,3,1,4,6,7
1,2,3,4,5,5,7
7,6,5,2,3,2,1
7,6,6,4,3,2,1
sed '1d'
删除双headerawk
会将 header 行保存在header
数组中;然后每 2 取 2 行并遍历所有字段并将它们保存在 2 个数组l1
和l2
中,然后我们逐一比较这 2 个数组的元素,一旦我们得到第一个差异我们打印它,如果我们已经打印了一个差异,那么p
变成0
并且我们更改我们打印的输出以遇到新的差异
最终输出:(对于我的 2 个输入文件)
Item FILE1 FILE2
1 D=1 D=4
--- ---
--- ---
7 C=5 C=6
--- ---
awk代码格式为-F',':
NR==1{
print "Item\tFILE1\tFILE2";
for(i=1;i<=NF;i++)header[i]=$i;
}
NR>1{
for(i=1;i<=NF;i++)l1[i]=$i;
getline;
for(i=1;i<=NF;i++)l2[i]=$i;
p=1;
for(i=1;i<=NF;i++){
if(l1[i]!=l2[i])
if(p){
print l1[1]"\t"header[i]"="l1[i]"\t"header[i]"="l2[i];
p=0;
}
else
print " \t---\t---"
}
}
如果你想显示所有差异使用
NR==1{
print "Item\tFILE1\tFILE2";
for(i=1;i<=NF;i++)header[i]=$i;
}
NR>1{
for(i=1;i<=NF;i++)l1[i]=$i;
getline;
for(i=1;i<=NF;i++)l2[i]=$i;
p=1;
for(i=1;i<=NF;i++){
if(l1[i]!=l2[i])
if(p){
print l1[1]"\t"header[i]"="l1[i]"\t"header[i]"="l2[i];
p=0;
}
else
print " \t"header[i]"="l1[i]"\t"header[i]"="l2[i];
}
}
或在一个命令中:
paste -d '\n' file1 file2 | sed '1d' | awk -F',' 'NR==1{print "Item\tFILE1\tFILE2";for(i=1;i<=NF;i++)header[i]=$i;}NR>1{for(i=1;i<=NF;i++)l1[i]=$i;getline;for(i=1;i<=NF;i++)l2[i]=$i;p=1;for(i=1;i<=NF;i++){if(l1[i]!=l2[i])if(p){print l1[1]"\t"header[i]"="l1[i]"\t"header[i]"="l2[i];p=0;}else print " \t"header[i]"="l1[i]"\t"header[i]"="l2[i]; }}'
这会产生以下输出:
Item FILE1 FILE2
1 D=1 D=4
E=4 E=5
F=6 F=5
7 C=5 C=6
D=2 D=4
~> ( nl file1.txt && nl file2.txt ) | sort | awk 'BEGIN{cnt=1;print "Item\tFILE1\tFILE2"}{if (NR==1) split(,col,",");}{if ((NR%2)==1){split(,data_2_NR,",");}else {split(,data_1_NR,","); for (i in data_1_NR) if (data_1_NR[i]!=data_2_NR[i]) print cnt++ "-" data_1_NR[1] "\t"col[i]"="data_1_NR[i] "\t"col[i]"=" data_2_NR[i] }}' }}'
输出:
Item FILE1 FILE2
1-1 F=6 F=5
2-7 C=6 C=5
解释:
为每个文件添加行号并排序结果
( nl file1.txt && nl file2.txt ) | sort | \
输出:
1 A,B,C,D,E,F,G
1 A,B,C,D,E,F,G
2 1,2,3,4,5,5,7
2 1,2,3,4,5,6,7
3 7,6,5,4,3,2,1
3 7,6,6,4,3,2,1
开始计数器 (cnt) 用于差异数和打印 table 标题
awk 'BEGIN{cnt=1;print "Item\tFILE1\tFILE2"}\
从第一行获取列名称(拆分 $2 因为我们需要原始内容而不是编号,编号用于排序)
{if (NR==1) split(,col,",");}\
由于我们已经完成了初始排序,我们可以查看奇数行和偶数行的差异 将奇数行拆分为名为 data_2_NR
的数组 {if ((NR%2)==1){split(,data_2_NR,",");}\
偶数行到名为 data_1_NR
的数组 else {split(,data_1_NR,",");\
运行 data_1_NR & data_2_NR 数组中的所有列并比较每个数组单元格
for (i in data_1_NR) if (data_1_NR[i]!=data_2_NR[i])\
如果它们在 table
中的打印行不同 print cnt++ "-" data_1_NR[1] "\t"col[i]"="data_1_NR[i] "\t"col[i]"=" data_2_NR[i]}}' }}'
输出
Item FILE1 FILE2
1-1 F=6 F=5
2-7 C=6 C=5