过滤CSV文件

时间:2013-08-20 23:17:54

标签: csv sed awk grep

我有一个csv文件和另一个文本文件(比如file1.csv和file2.txt)。文本文件有一列。现在,我想根据文本文件中的数据过滤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

4 个答案:

答案 0 :(得分: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 :(得分:1)

对于使用awk的解决方案,请参阅answer kev

要使用grep -f改进解决方案,请考虑使用bash process substitution

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

这在sed中的行上使用file2.txt将插入符号放在每行的开头,并在末尾放置一个逗号,这样当被视为正则表达式时(GNU?){{ 1}},模式只匹配行开头的确切字段值。如果您没有grep,则可以使用:

bash

但是,当您指定sed 's/.*/^&,/' file2.txt | grep -f - file1.csv 时,并非所有版本的grep都读取标准输入(例如,Mac OS X上的版本不会,但GNU -f -会这样做。)< / p>

或者,您可以使用grep命令,并使用适当的排序:

join

如果您确信文件已经排序,您可以将其简化为:

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

在Perl中,您可以使用:

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

也可能有其他方法可以做到这一点;例如,您可能会发现Text::CSV等模块的用途。

但是,此代码会读取每一行。如果它来自第一个文件,则会创建一个条目#!/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; } 来记录该号码。秩序和重复无所谓。在第二个(和后续)文件中,它将第一个逗号分隔的字段拆分出行,并检查是否在第一个文件中找到了该数字;如果是这样,它打印整行。 $rows{$_}++块检测代码何时在第一个文件上达到EOF(特别是),并设置continue。它与$file = 1;解决方案是同构的。这有点冗长。有awk模式(-a模式),但由于这两个文件需要区别对待,因此让它正常工作有点棘手。

其中,我认为awk解决方案可能是最好的,只要grep -f不是太大(而且我不确定限制是多少 - 但可能非常大)。

对于通用CSV文件操作工具,请考虑csvfix

答案 2 :(得分:0)

尝试以下命令:

grep -F -f file2.txt file1.csv

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

答案 3 :(得分:0)

对于Windows命令版:

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