【问题标题】:Fastest way to find lines in file1 which contains any keywords from file2?在file1中查找包含file2中任何关键字的行的最快方法?
【发布时间】:2017-02-19 21:37:22
【问题描述】:

我有两个文件。第一个文件有三十万条记录显示示例 (file1),第二个文件有十万条记录,显示示例 (file2)。我基本上用file1file2 上的每个条目进行grep,并检索file1 中的所有内容。我正在使用普通的 for 循环执行此操作:

for i in `cat file2.txt`; do cat file1 | grep -i -w $i; done > /var/tmp/file3.txt

由于数据太大,我需要 8 多个小时才能完成此操作。我需要您的专业知识,让我选择如何以有效的方式在不到 2-3 小时内完成此操作.

示例条目

文件1

server1:user1:x:13621:22324:User One:/users/user1:/bin/ksh |  
server1:user2:x:14537:100:User two:/users/user2:/bin/bash |  
server1:user3:x:14598:24:User three:/users/user3:/bin/bash |  
server1:user4:x:14598:24:User Four:/users/user4:/bin/bash |  
server1:user5:x:14598:24:User Five:/users/user5:/bin/bash | 

文件2

user1  
user2  
user3  

【问题讨论】:

  • 当我遇到类似的问题时,我不得不重新编译 grep,以便 -Ff 选项使用的缓冲区将整个搜索目标文件都放入其中。gnu -@987654331 可能@ 选项自动调整它的内存消耗。但是使用 man grep 并阅读有关 -F 的信息。另请查看是否有限制部分。否则,您可以使用 awk 构建类似的工具(假设有足够的可用内存来保存所有 file2。在此处搜索已发布的类似 Q。祝您好运。
  • 嗨 Shelter,感谢您的回复,这是手册页中的内容,您建议我执行 grep -fF 看看是否有帮助? -F 使用固定字符串进行匹配。将每个指定的模式视为字符串而不是正则表达式。如果输入行包含作为连续字节序列的任何模式,则匹配该行。空字符串匹配每一行。有关详细信息,请参阅 fgrep(1)。
  • 这可以被认为是这里许多类似帖子的重复。例如看这篇文章:stackoverflow.com/questions/42239179/…
  • 谢谢乔治,你说得对,我可以从你分享的帖子中获取一些东西,这将帮助我得到我想要的东西。非常感谢,我会将这个问题标记为已完成。
  • 同时,cat +grep 是一个糟糕的选择。您可以直接 grep 文件,您不需要先有猫。您还可以自动为 grep 提供模式,甚至不需要 file2 的循环。因此,您可以用一个简单的命令替换您的整个代码:grep -f file2 file1 甚至更好的grep -F -f file2 file1。不要害怕使用 -F。

标签: shell file file-comparison data-comparison


【解决方案1】:

试一试。

测试数据:

%_Host@User> head file1.txt file2.txt
==> file1.txt <==
server1:user1:x:13621:22324:User One:/users/user1:/bin/ksh |
server1:user2:x:14537:100:User two:/users/user2:/bin/bash |
server1:user3:x:14598:24:User three:/users/user3:/bin/bash |
server1:user4:x:14598:24:User Four:/users/user4:/bin/bash |
server1:user5:x:14598:24:User Five:/users/user5:/bin/bash |

==> file2.txt <==
user1
user2
user3
#user4
%_Host@User>

输出:

    %_Host@User> ./2comp.pl file1.txt file2.txt   ; cat output_comp
    server1:user1:x:13621:22324:User One:/users/user1:/bin/ksh |
    server1:user3:x:14598:24:User three:/users/user3:/bin/bash |
    server1:user2:x:14537:100:User two:/users/user2:/bin/bash |
    %_Host@User>
    %_Host@User>

脚本:请再试一次。重新检查文件顺序。首先是文件 1,然后是第二个文件:./2comp.pl file1.txt file2.txt

%_Host@User> cat 2comp.pl
#!/usr/bin/perl

use strict ;
use warnings ;
use Data::Dumper ;

my ($file2,$file1,$output) = (@ARGV,"output_comp") ;
my (%hash,%tmp) ;

(scalar @ARGV != 2 ? (print "Need 2 files!\n") : ()) ? exit 1 : () ;

for (@ARGV) {
  open FH, "<$_" || die "Cannot open $_\n" ;
  while (my $line = <FH>){$line =~ s/^.+[()].+$| +?$//g ; chomp $line ; $hash{$_}{$line} = "$line"}
  close FH ;}

open FH, ">>$output" || die "Cannot open outfile!\n" ;
foreach my $k1 (keys %{$hash{$file1}}){
  foreach my $k2 (keys %{$hash{$file2}}){
    if ($k2 =~ m/^.+?$k1.+?$/i){    # Case Insensitive matching.
      if (!defined $tmp{"$hash{$file2}{$k2}"}){
        print FH "$hash{$file2}{$k2}\n" ;
        $tmp{"$hash{$file2}{$k2}"} = 1 ;
                }}}} close FH  ;
# End.
%_Host@User>

祝你好运。

【讨论】:

  • 亲爱的朋友,您完成了这项工作,这很有效。太棒了..我再次检查的是区分大小写的场景,我做了一个小测试,更改了 file2 中的条目,将 user3 设置为 USER3,但没有用。这会是简单的改变吗​​?你也可以考虑一下吗?因为 file2 可能有这样的条目。
  • 请在脚本中查看我更新的评论。它应该这样做!
  • 非常感谢您完成了这项工作。我现在将尝试在我的三十万记录上运行它,看看它需要多长时间。再次感谢朋友。
猜你喜欢
  • 1970-01-01
  • 2017-02-19
  • 1970-01-01
  • 1970-01-01
  • 2016-02-11
  • 2021-03-06
  • 1970-01-01
  • 2019-06-26
  • 1970-01-01
相关资源
最近更新 更多