根据给定的ID列表从文本文件中提取所有行

jje*_*fer 4 unix perl awk

我有2个文本文件.file1包含ID列表:

11002
10995
48981
79600
Run Code Online (Sandbox Code Playgroud)

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
.....
Run Code Online (Sandbox Code Playgroud)

我试图选择file2ID(第一列)所在的所有行file1.目前,我正在做的是遍历第一个文件来创建一个正则表达式:

^\b11002\b\|^\b10995\b\|^\b48981\b|^\b79600\b
Run Code Online (Sandbox Code Playgroud)

然后运行:

grep '^11002\|^10995\|^48981|^79600' file2.txt
Run Code Online (Sandbox Code Playgroud)

但是当ID的数量file1太大(~2000)时,正则表达式会变得很长而grep变慢.还有另外一种方法吗?我正在使用Perl + Awk + ​​Unix.

Ale*_*lds 6

使用哈希表.它可能是内存密集型的,但查找是在恒定的时间内.这是一个高效且正确的过程 - 不是唯一的,但有效且正确 - 用于创建哈希表,使用file1as键和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;
Run Code Online (Sandbox Code Playgroud)

在Perl中有很多方法可以做同样的事情.也就是说,我重视清晰度和明确性,而不是花哨的默默无闻,因为你永远不知道什么时候你必须回到Perl脚本并进行更改,而且它们很难管理,就像它一样.一个人的意见.