我有一个包含超过百个单列条目的文件.我需要将这些条目中的每一个搜索到一个包含多列和超过一千个条目的文件中,并且需要一个输出文件.我试过这些代码:
#!/usr/bin/perl -w
use strict;
use warnings;
print "Enter the input file name:";
my $inputfile = <STDIN>;
chomp($inputfile);
print "\nEnter the search file name:";
my $searchfile=<STDIN>;
chomp($searchfile);
open (INPUTFILE, $inputfile) || die;
open (SEARCHFILE, $searchfile) || die;
open (OUT, ">write.txt") || die;
while (my $line=<SEARCHFILE>){
while (<INPUTFILE>) {
if (/$line/){
print OUT $_;
}
}
}
close (INPUTFILE) || die;
close (SEARCHFILE) || die;
close (OUT) || die;
Run Code Online (Sandbox Code Playgroud)
输出文件只有一行.它已将搜索文件中的术语搜索到输入文件中,但仅限于第一个术语,而不是全部.请帮忙!
当你INPUTFILE在内循环中读到它时,它会在第一轮中读到最后SEARCHFILE.因为它没有重置,所以文件句柄已用完并将始终返回eof.
如果有数百行,但不是几十万行,您可以先将其轻松读入数组,然后将其用于查找.它是单列的事实使这非常容易.请注意,这比下面的替代解决方案效率低.
chomp( my @needles = <SEARCHFILE> );
while (<INPUTFILE>) {
foreach my $needle (@needles) {
print OUT $_ if m/\Q$needle\E/; # \Q end \E quote regex meta chars
}
}
Run Code Online (Sandbox Code Playgroud)
或者,您也可以构建一个匹配所有字符串的大型查找正则表达式.这可能比为每行迭代数组更快.
# open ...
chomp( my @needles = <SEARCHFILE> );
my $lookup = join '|', map quotemeta, @needles;
my $lookup_regex = qr/$lookup/; # possibly with /i?
while (my $line = <INPUTFILE>) {
print OUT $line if $line =~ $lookup_regex;
}
Run Code Online (Sandbox Code Playgroud)
在quotemeta需要包含正则表达式元字符字符串一样的照顾/或者|甚至..它与使用\Q和\E上面一样.
还请使用三参数打开和命名文件句柄.
open my $fh_searchfile, '<', $searchfile or die $!;
open my $fh_inputfile, '<', $inputfile or die $!;
open my $fh_out, '>', 'write.txt' or die $!;
chomp( my @needles = <$fh_searchfile> );
# ...
Run Code Online (Sandbox Code Playgroud)
三参数打开非常重要,因为您正在接收用户输入并直接将其用作文件名.恶意用户可以输入类似的东西| rm -rf *,这会打开管道来删除我的所有文件而不询问程序.哎呀.但是如果'<'在其自己的参数中明确指定read open方法,则在第三个参数中忽略方法字符.
$fh正如名字所说,词汇文件句柄是词法,而INPUTFILEGLOB 则是全局的.如果你只有这个脚本而没有模块,那就没那么糟了,但只要你处理不同的软件包就会出现问题,因为那些是超全局的,程序的每个部分都会看到它们.这可能会导致名称冲突和奇怪的事情发生.