2013-08-20 88 views
1

我有一個csv文件和另一個文本文件(比如說file1.csv和file2.txt)。該文本文件有一列。現在,我想根據文本文件中的數據過濾csv文件。例如,過濾CSV文件

 
file1.csv 
----------- 
1,a,b,c 
2,d,e,f 
3,g,d,g 

file2.txt 
----------- 
1 
3 

我想要的結果是─

 
1,a,b,c 
3,g,d,g 
+0

好的。我能夠使用簡單的'grep'命令解決它。 grep -f file2.txt file1.csv。我只是好奇,看看有沒有其他的方法。 – Teja

+4

你的簡單的解決方案也會從'file1.csv'(更不用說'444,1,2,33')選擇'10,p,q,r'和'300,x,y,z'行;這可以嗎?如果沒有,你需要使用'join'命令,適當的排序,可能(或'awk'和關聯數組,或Perl,或者Python,或者'grep -f <(sed's /.*/^& ,/'file2.txt)file1.csv')。 –

+5

您可能還想看看[csvfix](http://code.google.com/p/csvfix)中用於處理CSV文件的工具。 –

回答

2

嘗試此命令:

awk -F, 'FNR==NR{a[$0];next};$1 in a' file2.txt file1.csv 

邏輯很簡單:

FOR each line in 'file2.txt' and 'file1.csv' 
    IF line is from 'file2.txt' 
     store it to array 'a' 
     CONTINUE 
    ENDIF 
    IF column 1 of line is in 'a' 
     PRINT line 
    ENDIF 
ENDFOR 
1

對於使用溶液awk,請參閱answerkev

對於使用grep -f一個改進的解決方案,可以考慮使用bashprocess substitution

grep -f <(sed 's/.*/^&,/' file2.txt) file1.csv 

這使用在file2.txtsed把一個脫字符號在每個行的開始和結束時逗號,以便當通過(GNU?)grep作爲正則表達式處理時,模式只匹配行首的精確字段值。如果你沒有做bash,您可以使用:

sed 's/.*/^&,/' file2.txt | grep -f - file1.csv 

然而,並不是所有grep閱讀版本標準輸入當指定-f -(在Mac OS X的版本不對,例如,但GNU grep呢)。

或者,你可以使用join命令,用適當的排序:

join -o 1.1,1.2,1.3,1.4 -t, <(sort file1.csv) <(sort file2.txt) 

如果您確信這些文件已經排序,你可以簡化到只是:

join -o 1.1,1.2,1.3,1.4 -t, file1.csv file2.txt 

在Perl,你可以使用:

#!/usr/bin/env perl 
use strict; 
use warnings; 

my $file = 0; 
my %rows; 

while (<>) 
{ 
    chomp; 
    $rows{$_}++ if ($file == 0); 
    if ($file == 1) 
    { 
     my($id) = split /,/; 
     print "$_\n" if defined $rows{$id}; 
    } 
} 
continue 
{ 
    $file = 1 if eof; 
} 

可能還有其他方法可以做 它也;例如,您可能會發現模塊的用途,例如Text::CSV

但是,這段代碼讀取每一行。如果它來自第一個文件,那麼它會創建一個條目$rows{$_}++來記錄該數字被看到。順序和重複無關緊要。在第二個(及後續)文件中,它將第一個逗號分隔字段分隔出來,並檢查在第一個文件中是否找到該號碼;如果是這樣,它會打印整行。 continue塊會檢測代碼在第一個文件(特別是)上到達EOF的時間,並在其設置時設置$file = 1;。它與awk解決方案同構。這有點冗長。有-a模式(awk模式),但因爲這兩個文件需要不同的處理,讓它正常工作有點棘手。

其中,我認爲grep -f解決方案可能是最好的,只要file2.txt不是太大(我不知道限制會是什麼 - 但可能會驚人地大)。

對於通用的CSV文件操作工具,請考慮csvfix

0

嘗試下面的命令:

的grep -F -f FILE2.TXT file1.csv

1,A,B,C
3,G,d,克

0

對於Windows命令版本:

findstr /G:file2.txt file1.csv > result.csv