按列标题合并两个 csv 文件

按列标题合并两个 csv 文件

我有两个 csv 文件:

成功.csv

“ID”、“旧 ID”、“字段 1”、“字段 2”

1,1111,google,news
2,2222,yahoo,news

错误.csv

“旧 ID”、“字段 1”、“字段 2”、“消息”

3333,aol,news,"Failed to upload data"    
4444,cbs,news,"Alredy exists"

如何合并这两个文件并创建一个新文件,如下所示?我无法使用索引,因为字段的大小和顺序会不断变化。

结果.csv

“ID”、“旧 ID”、“消息”

1,1111,""
2,2222,""
"",3333,"Failed to upload data"
"",4444,"Alredy exists"

要求是创建results.csv仅包含success.csv和中的三列的文件error.csv

  1. 如果该行已成功加载,那么我们会在成功文件中获得“ID”作为第一列,而没有“Message”列

  2. 如果失败,我们会在“消息”字段中收到错误,该字段始终是文件中的最后一个字段。在这种情况下,“ID”将为空。

读取值如下success.csv

awk '{print $1, $2;}' success.csv

读取值如下error.csv

awk '{print $1, NF;}' error.csv

我无法找到一种方法来组合这两个语句并将结果写入文件。

答案1

这个问题不是很清楚,但我相信您正在寻找以下结构:

awk 'BEGIN{FS=OFS=","}NR==FNR{print $1,$2,"\"\"";next}{print "\"\"",$1,$NF}' success.csv error.csv

解释:

  • 首先,在一开始我们将字段分隔符(FS)和输出字段分隔符(OFS)设置为,
  • 我们一次性处理这两个文件,但我们检查处理的是哪一个。当当前行号等于当前文件 ( NR==FNR) 中的当前行号时,处理第一个。
  • 因此,对于第一个文件(success.csv),我们打印$1,$2,"\"\"",而对于第二个文件(error.csv),我们打印"\"\"",$1,$NF

结果是:

1,1111,""
2,2222,""
"",3333,"Failed to upload data"    
"",4444,"Alredy exists"

答案2

使用磨坊主( mlr):

$ mlr --csv unsparsify then cut -f ID,'Legacy ID',Message  success.csv error.csv
ID,Legacy ID,Message
1,1111,
2,2222,
,3333,Failed to upload data
,4444,Alredy exists

这使用 Miller 的“unsparsify”操作根据可用标头合并两个文件中的数据,并将空字符串分配为文件中特定标头不存在的值。然后执行“剪切”操作以仅提取字段的子集。

字段的顺序取决于 Miller 找到它们的顺序,因此如果以相反的顺序给出文件,您会得到不同的顺序:

$ mlr --csv unsparsify then cut -f ID,'Legacy ID',Message  error.csv success.csv
Legacy ID,Message,ID
3333,Failed to upload data,
4444,Alredy exists,
1111,,1
2222,,2

您可以使用“cut”后的“reorder”操作以显式顺序对字段重新排序,而不依赖于输入文件中字段的顺序:

mlr --csv \
    unsparsify then \
    cut -f ID,'Legacy ID',Message then \
    reorder -f ID,'Legacy ID',Message \
    error.csv success.csv

相关内容