2013-07-08 83 views
1

我有2个CSV文件,我正在寻找一种方式使用特定的列对它们进行比较,一旦发现匹配,我需要从匹配的拍摄另一列的值行并将其放在另一条记录的相应列中。比较2个CSV文件,并替换更新的值

我会尽力解释多一点点。

一个CSV具有product_id,product_name,brand_name,price 其他有product_id,product_category,product_name,brand_name,price

我需要寻找具有匹配product_id值的行的2个文件进行比较,一旦发现我需要从文件1 price值,并把它匹配的记录的price文件2.

经过广泛的研究,我得出的结论是,这可能使用PowerShell实现的。

没有人有,我怎么能做到这一点任何想法?感谢您的时间。

+0

你需要自动化这个还是只是一次性动作? – saamorim

+0

只需要一次,我会再次在未来,但手动 –

回答

2

由于只是一次行动。您可以在电子表格(Google Docs,Excel,...)中打开CSV文件并执行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功能将搜索D2细胞对区域A的第一列中的值的完全匹配:B,和返回该区域第二列的值。如果VLOOKUP失败,iferror将返回NULL。

所以在这种情况下,单元格F2将在列A上查找产品ID“2”(单元格d2)。它在行3中找到产品标识“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 
+0

很有意思,打算现在就试试吧,我会回来的报告。谢谢你这么描述这个问题,就必须采取你一些时间来写了。我真的很感激 –

+0

大家好。这像一个魅力工作,我不能感谢你足够的知识 –

+2

。标记为接受,请 – saamorim

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(在这种情况下,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

$ awk -F, 'FNR==NR{print "-";} (1){print;}' a.csv b.csv # or: 
$ awk -F, 'FNR==NR{print "-";} {print;}' a.csv b.csv 
- 
#product_id,product_name,brand_name,price 
- 
1,pname1,bname1,100 
- 
10,pname10,bname10,200 
- 
20,pname20,bname20,300 
#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 

$ awk -F, 'FNR==NR{print "-";} FNR!=NR{print;}' a.csv 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的“本节以下执行;“上面的评论原则上是错误的 - 即使这就是这个特定的例子最终表现如何。