0

如何获得两个 .csv 文件之间的交线?我的问题似乎很难理解,但我会给你一个这样的例子:

我有 2 个 .csv 文件:

+---+-------+----+ +-----------------+
| 一个 | 乙| C | | 一个 | 乙| C |
+---+-------+----+ +----+--------+----+
| 1 | 蚂蚁| 14 |* | 6 | 风扇 | 12 |
| 2 | 鸟| 高分辨率照片| CLIPARTO 11 | | 7 | 枪| 55 |*
| 3 | 猫 | 21 |* | 8 | 马| 高分辨率照片| CLIPARTO 21 |*
| 4 | 狗 | 55 |* | 9 | 冰 | 15 |
| 5 | 鸡蛋| 99 | | 10 | 罐子 | 14 |*
+---+-------+---+ +----+--------+----+
     表 1 表 2

因此,如果我使用表 1 过滤表 2,我将得到如下输出:

+----------------+
| 一个 | 乙| C |
+---+-------+----+     
| 7 | 枪| 55 |*     
| 8 | 马| 高分辨率照片| CLIPARTO 21 |*    
| 10| 罐子 | 14 |*       
+---+-------+----+     
    表3                   

是的,我使用表 1 的最后一列过滤表 2

我怎样才能用任何工具像这样过滤它?

4

4 回答 4

1

假设您的输入文件只包含数字和字符串,没有额外的表格格式字符(只是一个\t单独的文件),您可以执行以下操作:

表1(t1.txt):

1       ant     14
2       bird    11
3       cat     21
4       dog     55
5       egg     99

表2(t2.txt):

6       Fan     12
7       gun     55
8       horse   21
9       ice     15
10      jar     14

以及执行和输出:

$ join -j 3 -o '2.1,2.2,2.3' <(sort -k 3n t1.txt) <(sort -k 3n t2.txt) | sort -n
7 gun 55
8 horse 21
10 jar 14

或者,如果您有很多列,您可以先只提取过滤列,然后再执行选择。此外,您可以在join不指定初始模式的情况下输出 -input 文件(在您的情况下为所有列)。执行后,您只需选择您实际想要显示的列(使用cut,例如):

$ join -2 15 <(cut -f 15 t1.txt | sort) <(sort -k 15 t2.txt) | sort -n

注意cut用作\t默认分隔符 - 可以用 flag 重新定义-d <separator>。无论如何,正如@EmmadKareem 所指出的,您最好使用适当的数据库来完成这项任务——因为它将有几十个优化,您的十万/百万行肯定需要。

于 2013-10-19T14:05:20.340 回答
1

这可能对您有用(GNU sed):

sed -r 's/(\S+\s?){3}/\/(^\\S+\\s){2}\1$\/p/' file1.csv | sed -nrf - file2.csv

对于以空格或制表符分隔的文件。

对于逗号分隔的文件:

sed -r 's/([^,]+,?){3}/\/(^[^,]+,){2}\1$\/p/' file1.csv | sed -nrf - file2.csv

这通过从第一个表创建一个 sed 脚本然后使用它来过滤第二个表来工作。

于 2013-10-19T17:55:01.883 回答
1

根据上面的评论,这是我所做的:

Create table T1 (A INT, B VARCHAR(100), C INT);

Create table T2 (A INT, B VARCHAR(100), C INT);

Insert into T1 Values (1, 'ant',14);
Insert into T1 Values (2, 'bird',11);
Insert into T1 Values (3, 'cat',21);
Insert into T1 Values (4, 'dog',55);
Insert into T1 Values (5, 'egg',99);

Insert into T2 Values (6, 'fan',12);
Insert into T2 Values (7, 'gun',55);
Insert into T2 Values (8, 'horse',21);
Insert into T2 Values (9, 'ice',15);
Insert into T2 Values (10, 'jar',14);

我不确定您是否有数据已经​​在表中,有一些工具可以将 csv 文件导入到您的数据库中。

如果您要经常运行查询,那么在每个表的 A 列上建立索引将加快该过程。我没有为这个简单的案例建立任何索引。

获得结果所需的选择是:

select * from t2,t1 where t2.c = t1.c order by t2.a

如果您对结果感到满意,可以将其放在这样的表中(SQL Server)

SELECT T2.A, T2.B , T2.C INTO TEST FROM t2,t1 where t2.c = t1.c order by t2.a

我希望这是你想要的...

于 2013-10-26T09:24:51.617 回答
0

这是Perl中的一个脚本,可以完成您想要的工作。

它通过扫描第一个文件并将第三列的值保存在内存中来工作。然后它扫描第二个文件,并且对于读取的每一行,它将第三列的值与内存中的值进行比较,如果匹配,则打印该行。

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

my %seen;

open my $file1_fh, '<', 'file1.txt' 
    or die "Can't open file1.txt $!";

while (<$file1_fh>) {
    chomp;
    $seen{ (split)[2] } = 1; #assumes line are delimited by whitespace.
}

close $file1_fh;

open my $file2_fh, '<', 'file2.txt'
    or die "Can't open file2.txt $!";


while (<$file2_fh>) {
    chomp;
    my $third_column_value = (split)[2]; #assumes line are delimited by whitespace.
    say if $seen{ $third_column_value };
}

close $file2_fh;

__END__

#OUTPUT
7 gun 55
8 horse 21
10 jar 14
于 2013-10-19T15:35:03.437 回答