如何将csv文件读入数组,并用另一个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
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):
为了代码简洁,添加了variabek
,并将“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