Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 打印一个文件中的行与另一个文件中的模式匹配_Unix_Sed_Awk_Grep_Extract - Fatal编程技术网

Unix 打印一个文件中的行与另一个文件中的模式匹配

Unix 打印一个文件中的行与另一个文件中的模式匹配,unix,sed,awk,grep,extract,Unix,Sed,Awk,Grep,Extract,我有一个超过40000行的文件(file1),我想提取file2中匹配模式的行(大约6000行)。我像这样使用grep,但速度非常慢: grep -f file2 file1 > out 使用awk或sed有没有更快的方法 以下是我的文件的一些摘录: File1: scitn003869.2| scign003869 CGCATGTGTGCATGTATTATCGTATCCCTTG scitn007747.1| scign007747 CACGCAGACGCAGTGGAGCATTCCAG

我有一个超过40000行的文件(file1),我想提取file2中匹配模式的行(大约6000行)。我像这样使用grep,但速度非常慢:

grep -f file2 file1 > out
使用
awk
sed
有没有更快的方法

以下是我的文件的一些摘录:

File1

scitn003869.2| scign003869 CGCATGTGTGCATGTATTATCGTATCCCTTG
scitn007747.1| scign007747  CACGCAGACGCAGTGGAGCATTCCAGGTCACAA
scitn003155.1| scign003155  TAAAAATCGTTAGCACTCGCTTGGTACACTAAC
scitn018252.1| scign018252  CGTGTGTGTGCATATGTGTGCATGCGTG
scitn004671.2| scign004671  TCCTCAGGTTTTGAAAGGCAGGGTAAGTGCT
File2

scign000003
scign000004
scign000005
scign004671
scign000013

您可以尝试使用此awk:

awk 'BEGIN{i=0}
FNR==NR { a[i++]=$1; next }
{ for(j=0;j<i;j++)
    if(index($0,a[j]))
        {print $0;break}
}' file2 file1
awk'开始{i=0}
FNR==NR{a[i++]=$1;next}

{对于(j=0;jTry
grep-Fwf file2 file1>out


-F
选项指定纯字符串匹配,因此在不使用正则表达式引擎的情况下应该更快。

以下是如何在awk中执行此操作:

awk 'NR==FNR{pats[$0]; next} $2 in pats' File2 File1
使用60000行文件1(您的文件1重复8000次)和6000行文件2(您的文件重复1200次):

i、 它的速度和grep差不多。但需要注意的是,awk解决方案允许您选择一个特定字段进行匹配,这样,如果File2中的任何内容出现在File1中的任何其他位置,您将不会得到错误匹配。它还允许您一次匹配整个字段,因此如果您的目标字符串长度不同,并且您不需要“scign000003”例如,匹配“scign0000031”(尽管grep的-w提供了类似的保护)

为完整起见,以下是另一个awk解决方案的发布时间:

$ time awk 'BEGIN{i=0}FNR==NR{a[i++]=$1;next}{for(j=0;j<i;j++)if(index($0,a[j]))print $0}' File2 File1 > ou3

real    3m34.110s
user    3m30.850s
sys     0m1.263s

为了好玩,这里有一个Perl版本:

#!/usr/bin/perl
use strict;
use warnings;
my %patterns;
my $srch;

# Open file and get patterns to search for
open(my $fh2,"<","file2")|| die "ERROR: Could not open file2";
while (<$fh2>)
{
   chop;
   $patterns{$_}=1;
}

# Now read data file
open(my $fh1,"<","file1")|| die "ERROR: Could not open file1";
while (<$fh1>)
{
   (undef,$srch,undef)=split;
   print $_ if defined $patterns{$srch};
}

只是为了学习:我在解决同样的问题,我想出了各种解决方案(包括
read$line
loops等等)。当我找到上面找到的
grep
一行时,我仍然得到了错误的输出。然后我意识到我的模式文件有两行尾随行…因此
grep
从我的数据库中提取了我的所有行。道德:检查尾随空格/行。另外,在一个包含数百行的更大数据集上运行该命令s模式和
时间都无法计数。

工作得非常完美。比我的grep命令快得多。谢谢!如果使用
if(index($0,a[j]){print;break},您将获得一些效率。
思考得好,Glenn。谢谢。如果您对文件进行排序,您仍然可以进行优化(特别是如果一个在运行时几乎每次都是相同的,我猜这里是file2)这个作业只花了大约一秒钟!Fgrep是这个本机选项的等价物,可能仍然很少毫秒fastermy grep手册页说:“Fgrep与grep-F相同。当不推荐使用egrep或Fgrep时直接调用,…”虽然这可能符合OP的意思和要求,但我确实看到你提到了这一点,并将其描述为避免错误匹配的好处,OP应该意识到它实际上与他的代码不一样。他的代码会在任何地方找到匹配,而你的代码只会在第二个字段中找到匹配。+1很好。奇怪这是为什么比
awk
解决方案快两倍以上。顺便说一下,我假设您也将perl程序的输出保存到了一个文件中?(在您的回答中
/go.pl
之后没有重定向)这是我的“最佳”perl,我确实利用了我所知道的关于数据的一切,比如使用chop()和(undef,$srch,undef)丢弃我不需要的东西,awk也没有那么奢侈。我确实将它保存到了一个文件中,但只是复制和粘贴了计时,而不必编辑我的提示。我得到的测量结果与上述完全相反(见我更新的帖子)perl的速度是awk或grep的两倍。我怀疑Mark在计时之前没有运行脚本几次以说明缓存问题。真奇怪!我确实运行了几次,它们在我的Mac上都非常一致-它运行在SSD上,通常使计时一致-没有旋转延迟或寻道时间。idk。至少可以说,我觉得perl有点难读,但它看起来和我的awk脚本做的事情一样,只是手工编写循环并将行拆分为字段,所以我希望perl可能会稍微慢一点,因为与使用内置功能相比,必须手工编写循环/拆分代码,但我希望这两个脚本能够大概是在同一个球场。我想当你在谈论。1秒对2秒,这是在同一个球场对其他一些解决方案,在几分钟的顺序。啊,太感谢你了!我想知道为什么我的整个文件看起来像是返回的
grep-Fwf,如果你有“黑名单”,我会加上它您需要文件2中没有的所有内容,然后只需像这样添加
-v
grep-vFwf file2 file1>out
$ time ./go.pl > out2

real    0m0.203s
user    0m0.124s
sys     0m0.062s
#!/usr/bin/perl
use strict;
use warnings;
my %patterns;
my $srch;

# Open file and get patterns to search for
open(my $fh2,"<","file2")|| die "ERROR: Could not open file2";
while (<$fh2>)
{
   chop;
   $patterns{$_}=1;
}

# Now read data file
open(my $fh1,"<","file1")|| die "ERROR: Could not open file1";
while (<$fh1>)
{
   (undef,$srch,undef)=split;
   print $_ if defined $patterns{$srch};
}
time awk 'NR==FNR{pats[$0]; next} $2 in pats' file2 file1 > out
real    0m0.202s
user    0m0.197s
sys     0m0.005s

time ./go.pl > out2
real    0m0.083s
user    0m0.079s
sys     0m0.004s