Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.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
Perl 删除输入文件中的行,不包括另一个文件中列出的模式_Perl_Sed_Awk_Grep - Fatal编程技术网

Perl 删除输入文件中的行,不包括另一个文件中列出的模式

Perl 删除输入文件中的行,不包括另一个文件中列出的模式,perl,sed,awk,grep,Perl,Sed,Awk,Grep,我想从输入文件中删除与排除文件中列出的任何模式匹配的行 输入文件相当大(约500 MB),所以我也在寻找有效的解决方案 请注意,下面的示例只是一个示例,排除可能包含包含特殊字符的复杂模式,例如/ 包含排除列表的文件(异常) 输入文件(infle) 所需输出(输出文件) 在给定排除列表的情况下,我可以使用下面的命令,并且效果很好 egrep -v "Jun|Jul|Aug" infile > outfile 我的问题是如何从异常文件中获取管道|分隔字符串并将其传递给上面的grep命令?或者

我想从输入文件中删除与排除文件中列出的任何模式匹配的行

输入文件相当大(约500 MB),所以我也在寻找有效的解决方案

请注意,下面的示例只是一个示例,排除可能包含包含特殊字符的复杂模式,例如
/

包含排除列表的文件(异常

输入文件(infle

所需输出(输出文件

在给定排除列表的情况下,我可以使用下面的命令,并且效果很好

egrep -v "Jun|Jul|Aug" infile > outfile
我的问题是如何从异常文件中获取管道
|
分隔字符串并将其传递给上面的grep命令?或者有没有其他最佳方式来实现这一点

我必须将其作为
perl
解决方案的一部分来实现,在该解决方案中,进一步的处理是通过哈希实现的。但我对任何linux解决方案都持开放态度,因为我可以在perl脚本中执行这些命令

非常感谢您在这方面的帮助

更新

与此同时,人们正在帮助我解决他们的问题,我可以用
perl
编写下面的代码,而且它也起到了作用

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

open my $exfread, '<', "exception" or die $!;
chomp ( my @exclusions = <$exfread> );
close $exfread;
my $ex_str = join '|', @exclusions;
# print $ex_str . "\n";

open my $infread, '<', "infile" or die $!;
open my $outfwrite, '>', "outfile" or die $!;

while (<$infread>) {
    next if /${ex_str}/;    
    print $outfwrite $_;
    # do some more processing using hash
}

close $outfwrite;
close $infread;
#/usr/bin/perl
使用警告;
严格使用;

打开我的$exfread,“而不是在Perl之外,为什么不像这样在里面阅读和过滤呢

#!/usr/bin/env perl

use strict;
use warnings;

my $ifile = 'old.txt';
my $ofile = 'new.txt';

open (my $ifh, '<', $ifile) or die $!;
open (my $ofh, '>', $ofile) or die $!;

while (<$ifh>) {
    print $ofh $_ unless /^Jun|Jul|Aug/;
}

close ($ifh);
close ($ofh);
#/usr/bin/env perl
严格使用;
使用警告;
my$ifile='old.txt';
my$ofile='new.txt';
打开(我的$ifh,,$ofile)或死亡$!;
而(){
打印$ofh$除非/^Jun | Jul | Aug/;
}
关闭($ifh);
收盘价($ofh);

此程序应适合您的目的。它的工作原理是通过将每一行与交替操作符
|
连接,从
exception.txt
的内容中形成一个正则表达式。然后使用
qr
编译正则表达式

这应该证明是非常快的,因为每行只执行一个正则表达式比较

use strict;
use warnings;
use autodie;

my $regex = do {
  open my $in,  '<', 'exception.txt';
  my @infile = <$in>;
  chomp @infile;
  local $" = '|';
  qr/@infile/;
};

open my $in,  '<', 'infile.txt';
open my $out, '>', 'outfile.txt';

while (<$in>) {
  print $out $_ unless $_ =~ $regex;
}

对于您的示例,这一行适用于:

grep -vf exception infile

应执行与unix命令相同的操作。

感谢您的回复。但我的主要问题是从一个单独的文件中获取搜索模式列表。我知道我可以读取该文件并使用
join
。但搜索模式也可以包含
/
。请参阅@Borodin solution then。这是完美的一行!谢谢!我应该检查一下
mangrep
:(现在接受perl解决方案,但下次一定会在shell脚本中使用它。我认为这个解决方案不担心特殊字符,最好是
quotemeta()
它们?类似于:
s=join q{124;},map{$=q{124;\\ q}.$.q}\\E}@infle
然后执行
qr
?@Birei:绝对不会。在编译正则表达式之前将
quotemeta
应用于正则表达式将避开所有反斜杠,并使它们作为文字字符匹配。试试看。@Borodin效果很好!如果您能评论一下perl与grep one linerTrue的使用效率,我将不胜感激。我已经测试过了它意识到我错了:-)但是如何解决字符串中特殊字符的转义呢?@jkshah:我不能评论与Perl相比
grep
的效率,但是,正如我在你的问题上所评论的,除非两者都非常低效,它们之间没有什么可选择的。这正是我提供的解决方案,只是您不必要地为输入文件的每一行编译正则表达式。@Borodin看到了您的ans。肯定会尝试的。正如我所说,我的下一个目标将是选择运行时间更短的高效代码。在不同的方法之间几乎没有选择。一个500MB的文件并没有那么大,但从硬盘上读取它大约需要10秒钟,而写入相同的数据则需要大致相同的时间。相比之下,检查每行内容的处理时间微不足道,因此无论您选择哪种方法,运行时间都大约为20秒。@Borodin感谢您的详细解释。我知道解析数据并将其存储在另一个文件中不会花费太多时间。请注意,我必须对过滤后的数据创建一个大的散列。可能是我做这件事效率低下,因为它花了大约5分钟。您所描述的只是根据
异常
过滤
infle
outfile
。这应该只需要几秒钟。很明显,我不能评论你可能正在做的任何事情。
#!/usr/bin/env perl

use strict;
use warnings;

my $ifile = 'old.txt';
my $ofile = 'new.txt';

open (my $ifh, '<', $ifile) or die $!;
open (my $ofh, '>', $ofile) or die $!;

while (<$ifh>) {
    print $ofh $_ unless /^Jun|Jul|Aug/;
}

close ($ifh);
close ($ofh);
use strict;
use warnings;
use autodie;

my $regex = do {
  open my $in,  '<', 'exception.txt';
  my @infile = <$in>;
  chomp @infile;
  local $" = '|';
  qr/@infile/;
};

open my $in,  '<', 'infile.txt';
open my $out, '>', 'outfile.txt';

while (<$in>) {
  print $out $_ unless $_ =~ $regex;
}
Jan 02, 2013
Feb 02, 1988
Feb 02, 1988
Jan 02, 2013
Sep 02, 1988
Mar 02, 1988
Nov 02, 1988
grep -vf exception infile
grep -vf patternfile