我有2个csv文件,我正在寻找一种使用特定列比较它们的方法,一旦找到匹配项,我需要从匹配行中获取另一列的值并将其放入相应的列中另一条记录。
我会尝试解释一下。
一个csv有product_id,product_name,brand_name,price
另一个有product_id,product_category,product_name,brand_name,price
我需要通过查找具有匹配product_id
值的行来比较这两个文件,一旦找到,我需要从文件1中取出price
值并将其放入匹配的记录{文件2中的{1}}。
经过广泛研究后,我得出的结论是,这可以通过powershell实现。
有没有人对我如何做到这一点有任何想法?谢谢你的时间。
答案 0 :(得分:2)
因为只是一次性动作。您可以在电子表格中打开csv文件(google docs,excel,...)并执行VLOOKUP。很简单:
为了证明这一点,想象下面的电子表格,其中两个csv文件是并排的。首先是A列到B列,第二个是D列到F
| A | B | C | D | E | F
--+------------+-------+---+------------+------------------+-------
1 | product_id | price | | product_id | product_category | price
2 | 1 | 29.9 | | 2 | SOME CAT 1 | =IFERROR(VLOOKUP(D2;A:B;2;FALSE); "NULL")
3 | 2 | 35.5 | | 3 | SOME CAT 2 | =IFERROR(VLOOKUP(D3;A:B;2;FALSE); "NULL")
VLOOKUP
函数将在区域A:B的第一列上搜索D2单元格值的完全匹配,并从该列的第二列返回值区域。如果iferror
失败,VLOOKUP
将返回NULL。
因此,在这种情况下,在单元格F2上,将在A列上查找产品ID“2”(单元格d2)。它在第3行中找到产品ID“2”,并返回价格“35.5”(正在范围A:B)的第二行。计算完所有行后,结果将为:
| A | B | C | D | E | F
--+------------+-------+---+------------+------------------+-------
1 | product_id | price | | product_id | product_category | price
2 | 1 | 29.9 | | 2 | SOME CAT 1 | 35.5
3 | 2 | 35.5 | | 3 | SOME CAT 2 | NULL
答案 1 :(得分:1)
也可以使用awk
;说你有:
$ cat a.csv
#product_id,product_name,brand_name,price
1,pname1,bname1,100
10,pname10,bname10,200
20,pname20,bname20,300
$ cat b.csv
#product_id,product_category,product_name,brand_name,price
3,pcat3,pname3,bname3,42
10,pcat10,pname10,bname10,199
20,pcat20,pname20,bname20,299
30,pcat10,pname30,bname30,420
使用“FNR == NR”方法(参见例如> The Unix shell: comparing two files with awk):
$ awk -F, 'FNR==NR{if(!/^#/){a[$1]=$0;next}}($1 in a){split(a[$1],tmp,",");printf "%d,%s,%s,%s,%d\n",$1,$2,$3,$4,tmp[4];}' a.csv b.csv
10,pcat10,pname10,bname10,200
20,pcat20,pname20,bname20,300
将每个文件读入数组(参见例如Awking it – how to load a file into an array in awk | Tapping away):
$ awk -F, 'BEGIN{while(getline < "a.csv"){if(!/^#/){a[$1]=$0;}}close("a.csv");while(getline < "b.csv"){if($1 in a){split(a[$1],tmp,",");printf "%d,%s,%s,%s,%d\n",$1,$2,$3,$4,tmp[4];}}close("b.csv");}'
10,pcat10,pname10,bname10,200
20,pcat20,pname20,bname20,300
实质上,这两种方法都做同样的事情:
a.csv
),并将其行存储在关联数组a
中,由该行的第一个字段$1
键入/索引(在本例中为{ {1}}); product_id
);如果在数组b.csv
中找到每一行的第一个字段;然后输出当前行a
的前四个字段;和数组b.csv
price
)
不同之处在于,使用a
方法,将命令行上的输入文件指定为FNR==NR
的参数,基本上您只能将第一个文件标识为“特殊”,这样您就可以将其存储为数组;使用第二种方法,每个输入文件可以在一个单独的数组中解析 - 但是,输入文件在awk
脚本本身中指定,而不是在awk
的参数中指定 - 从那以后你就不会甚至需要使用awk
的参数,awk
脚本的整体需要在awk
块内发生。
当从文件中读取行时,它们会根据BEGIN{...}
命令行选项自动拆分到字段中,这些选项将逗号设置为分隔符;但是,当检索存储在数组中的行时,我们必须单独-F,
第一个细分:
split()
第二个细分:
FNR==NR # if FNR (input record number in the current input file) equals NR (total num records so far)
# only true when the first file is being read
{
if(!/^#/) # if the current line does not `!` match regex `/.../` of start `^` with `#`
{
a[$1]=$0; # assign current line `$0` to array `a`, with index/key being first field in current line `$1`
next # skip the rest, and start processing next line
}
}
# --this section below executes when FNR does not equal NR;--
($1 in a) # first, check if first field `$1` of current line is in array `a`
{
split(a[$1],tmp,","); # split entry `a[$1]` at commas into array `tmp`
printf "%d,%s,%s,%s,%d\n",$1,$2,$3,$4,tmp[4]; # print reconstructed current line,
# taking the fourth field from the `tmp` array
}
请注意BEGIN{ # since no file arguments here, everything goes in BEGIN block
while(getline < "a.csv"){ # while reading lines from first file
if(!/^#/){ # if the current line does not `!` match regex `/.../` of start `^` with `#`
a[$1]=$0; # store current line `$0` to array `a`, with index/key being first field in current line `$1`
}
}
close("a.csv");
while(getline < "b.csv"){ # while reading lines from second file
if($1 in a){ # first, check if first field `$1` of current line is in array `a`
split(a[$1],tmp,","); # (same as above)
printf "%d,%s,%s,%s,%d\n",$1,$2,$3,$4,tmp[4]; # (same as above)
}
}
close("b.csv");
} # end BEGIN
执行:
FNR==NR
这意味着“以下此部分在FNR不等于NR时执行; ”上面的注释原则上是错误的 - 即使这是特定示例最终表现的方式。