我有2个文本文件。 file1
包含ID列表:
11002
10995
48981
79600
file2
:
10993 item 0
11002 item 6
10995 item 7
79600 item 7
439481 item 5
272557 item 7
224325 item 7
84156 item 6
572546 item 7
693661 item 7
.....
我正在尝试从file2
中选择ID(第一列)位于file1
的所有行。目前,我正在做的是遍历第一个文件来创建一个正则表达式:
^\b11002\b\|^\b10995\b\|^\b48981\b|^\b79600\b
然后运行:
grep '^11002\|^10995\|^48981|^79600' file2.txt
但是当file1
中的ID数量太大(~2000)时,正则表达式变得很长而grep
变慢。还有另外一种方法吗?我使用的是Perl + Awk + Unix。
答案 0 :(得分:5)
使用hash table。它可能是内存密集型的,但查找是在恒定的时间内。这是一个高效且正确的过程 - 不是唯一的,但有效且正确 - 用于创建哈希表,使用file1
作为键,使用file2
查找哈希表中的键。如果键位于哈希表中,则该行将打印到标准输出:
#!/usr/bin/env perl
use strict;
use warnings;
open FILE1, "< file1" or die "could not open file1\n";
my $keyRef;
while (<FILE1>) {
chomp;
$keyRef->{$_} = 1;
}
close FILE1;
open FILE2, "< file2" or die "could not open file2\n";
while (<FILE2>) {
chomp;
my ($testKey, $label, $count) = split("\t", $_);
if (defined $keyRef->{$testKey}) {
print STDOUT "$_\n";
}
}
close FILE2;
在Perl中有很多方法可以做同样的事情。也就是说,我重视清晰度和明确性,而不是花哨的默默无闻,因为你永远不知道什么时候你必须回到Perl脚本并进行更改,而且它们很难管理,就像它一样。一个人的意见。
答案 1 :(得分:4)
awk 'NR==FNR{tgts[$1]; next} $1 in tgts' file1 file2
查找
$ cat file1
11002
10995
48981
79600
$ cat file2
10993 item 0
11002 item 6
10995 item 7
79600 item 7
439481 item 5
272557 item 7
224325 item 7
84156 item 6
572546 item 7
693661 item 7
$ awk 'NR==FNR{tgts[$1]; next} $1 in tgts' file1 file2
11002 item 6
10995 item 7
79600 item 7
答案 2 :(得分:2)
使用grep
:
$ grep -f f1 f2
11002 item 6
10995 item 7
79600 item 7
注意:我在多个系统上测试了很多建议的答案,有些只显示最后一个匹配79600 item 7
!
答案 3 :(得分:2)
我建议使用专门设计的工具。使用join命令。 “男人加入”了解更多信息。
linux_prompt> join file1 file2
11002 item 6
10995 item 7
79600 item 7
答案 4 :(得分:1)
将第一个文件的所有元素加载到哈希中。
对于第二个文件的每一行,
使用正则表达式^(\d*)
提取数字
如果哈希包含提取的数字,则将其打印
答案 5 :(得分:0)
使用进程替换将file1中的ID转换为正则表达式:
grep -f <(sed 's/.*/^&\\b/' file1) file2
我假设您正在使用bash或类似功能的shell
答案 6 :(得分:0)
简单的perl解决方案是使用散列并计算所追求的数字的出现次数。
perl -lanwe 'print if $a{$F[0]}++ == 1;' file1.txt file2.txt
我从您的示例数据中获得以下输出:
11002 item 6
10995 item 7
79600 item 7
请注意,您需要在命令行上以正确的顺序使用这些文件。
这将打开并读取输入文件名(-n
),将行(-a
)自动分割为@F
,然后打印每一行,如果散列中的值为该数字等于1.如果要从file2打印多个值,只需将== 1
更改为>= 1
。
请注意,在完成相等性比较后应用++
运算符。