如何将csv文件读入数组,并用另一个csv文件中的条目进行比较和替换?

如何将csv文件读入数组,并用另一个csv文件中的条目进行比较和替换?,csv,awk,sed,Csv,Awk,Sed,我有两个csv文件file1.csv和file2.csv file1.csv包含4列 文件1: Header1,Header2,Header3,Header4 aaaaaaa,bbbbbbb,ccccccc,ddddddd eeeeeee,fffffff,ggggggg,hhhhhhh iiiiiii,jjjjjjj,kkkkkkk,lllllll mmmmmmm,nnnnnnn,ooooooo,ppppppp 文件2: "Header1","Header2","Header3" "aaaaa

我有两个csv文件
file1.csv
file2.csv

file1.csv
包含4列

文件1:

Header1,Header2,Header3,Header4
aaaaaaa,bbbbbbb,ccccccc,ddddddd
eeeeeee,fffffff,ggggggg,hhhhhhh
iiiiiii,jjjjjjj,kkkkkkk,lllllll
mmmmmmm,nnnnnnn,ooooooo,ppppppp
文件2:

"Header1","Header2","Header3"
"aaaaaaa","cat","dog"
"iiiiiii","doctor","engineer"
"mmmmmmm","sky","blue"
因此,我要做的是逐行读取
file1.csv
,将每个条目放入一个数组,然后将该数组的第一个元素与
file2.csv的第一列进行比较,如果存在匹配项,则将file1.csv的第1列和第2列替换为file2.csv的对应列

因此,我期望的输出是:

cat,dog,ccccccc,ddddddd
eeeeeee,fffffff,ggggggg,hhhhhhh
doctor,engineer,kkkkkkk,lllllll
sky,blue,ooooooo,ppppppp
只有一列可替换时,我可以这样做。
这是我的密码:

awk -F'"(,")?' '
NR==FNR { r[$2] = $3; next }
{ for (n in r) gsub(n,r[n]) } IGNORECASE=1' file2.csv file1.csv>output.csv
最后一步是将整个数组转储到一个包含10列的文件中。
有什么可以改进或更正代码的建议吗

编辑:考虑到您的输入文件2的日期为
“ytest”,“test2”
等格式,如果是,请尝试以下内容。(感谢Tiw在其帖子中提供此示例)



你能试试下面的吗

awk '
BEGIN{
  FS=OFS=","
}
FNR==NR{
  a[$1]=$0
  next
}
a[$1]{
  print a[$1],$NF
  next
}
1'  Input_file2  Input_file1
awk '
BEGIN{
  FS=OFS=","
}
FNR==NR{
  a[tolower($1)]=$0
  next
}
a[tolower($1)]{
  print a[tolower($1)],$NF
  next
}
1'  Input_file2  Input_file1
或者,如果输入文件中有小写字母和大写字母的组合,请尝试以下操作

awk '
BEGIN{
  FS=OFS=","
}
FNR==NR{
  a[$1]=$0
  next
}
a[$1]{
  print a[$1],$NF
  next
}
1'  Input_file2  Input_file1
awk '
BEGIN{
  FS=OFS=","
}
FNR==NR{
  a[tolower($1)]=$0
  next
}
a[tolower($1)]{
  print a[tolower($1)],$NF
  next
}
1'  Input_file2  Input_file1

根据您的示例数据和评论中的描述,请尝试以下操作:
(从您自己的代码判断,字段周围可能有引号,因此我没有尝试回答。)

例如:

另一种方式,更详细,但我认为最好让您理解(GNU awk):


为了代码简洁,添加了variabe
k
,并将
“if”
移动到其中。

,其中任一文件中包含任意awk和任意数量的字段:

$ cat tst.awk
BEGIN { FS=OFS="," }
{
    gsub(/"/,"")
    key = tolower($1)
}
NR==FNR {
    for (i=2; i<=NF; i++) {
        map[key,i] = $i
    }
    next
}
{
    for (i=2; i<=NF; i++) {
        $(i-1) = ((key,i) in map ? map[key,i] : $(i-1))
    }
    print
}

$ awk -f tst.awk file2 file1
Header2,Header3,Header3,Header4
cat,dog,ccccccc,ddddddd
eeeeeee,fffffff,ggggggg,hhhhhhh
doctor,engineer,kkkkkkk,lllllll
sky,blue,ooooooo,ppppppp
$cat tst.awk
开始{FS=OFS=“,”}
{
gsub(/“/,”)
钥匙=托洛尔(1美元)
}
NR==FNR{

例如(i=2;我看到你的个人资料后才知道,从最后几个问题中,你没有选择正确的答案,所以请你这样做(在你发表文章之后)当你在帖子中看到足够多的答案时,你可以选择其中任何一个作为正确答案@AnujKulkarni@Tiw是,我的file2.csv可能有引号。我自己创建file2.csv,而file1.csv是工具生成的文件。因此,在创建file2.csv时,我使用了引号。@提示是,这是正确的。不会有逗号。我使用引号因为文件2可能有两个以上空格分隔的单词(如一个句子)。@AnujKulkarni。建议发布靠近输入文件的示例,请编辑您的帖子,然后让我们知道。如果您的输入是逗号分隔的,那么空格或制表符就像任何其他字符一样,您不需要在字段周围加引号,除非它们包含逗号或换行符。它们可以包含换行符吗?谢谢,就像您所说的那样,第二种方法更容易理解。我尝试过使用它,并且效果很好s、 @AnujKulkarni当然,很高兴它能帮上忙:)谢谢你的努力,伙计,我现在正在试验你的代码。
NR==FNR
块中的代码将
file2
中的值一次存储在map数组中的一个字段中,第二个块中的循环一次访问该数组中的一个字段中的值。
awk 'BEGIN{FS=OFS=","}
    NR==FNR{for(i=1;i<=NF;i++)$i=gensub(/^"(.*)"$/,"\\1",1,$i);a[$1]=$2;b[$1]=$3;next}
    $1 in b{$2=b[$1];}
    $1 in a{$1=a[$1];}
    1' file2.csv file1.csv
awk 'BEGIN{FS=OFS=","}
    NR==FNR{gsub(/^"|"$/,"");gsub(/","/,",");k=tolower($1);a[k]=$2;b[k]=$3;next}
    {k=tolower($1);if(a[k]){$2=b[k];$1=a[k]}}
    1' file2.csv file1.csv
$ cat tst.awk
BEGIN { FS=OFS="," }
{
    gsub(/"/,"")
    key = tolower($1)
}
NR==FNR {
    for (i=2; i<=NF; i++) {
        map[key,i] = $i
    }
    next
}
{
    for (i=2; i<=NF; i++) {
        $(i-1) = ((key,i) in map ? map[key,i] : $(i-1))
    }
    print
}

$ awk -f tst.awk file2 file1
Header2,Header3,Header3,Header4
cat,dog,ccccccc,ddddddd
eeeeeee,fffffff,ggggggg,hhhhhhh
doctor,engineer,kkkkkkk,lllllll
sky,blue,ooooooo,ppppppp