Arrays 检查数据文件中的行是否包含数组元素

Arrays 检查数据文件中的行是否包含数组元素,arrays,perl,Arrays,Perl,我有一个包含关键字列表的文件。我有第二个数据文件,其中包含数千行数据。我已经将包含关键字的文件读入了一个数组,现在我想获取数组中的第一个元素,循环文件中的行,并打印包含该数组元素的任何值。然后移动到数组中的下一个元素并重复该过程 下面是到目前为止我的代码,但它似乎没有做任何事情。我不知道我想做的是否可能。任何帮助都将不胜感激 use strict; use warnings; my $keywords= shift; my $data= shift; #reading in keyword

我有一个包含关键字列表的文件。我有第二个数据文件,其中包含数千行数据。我已经将包含关键字的文件读入了一个数组,现在我想获取数组中的第一个元素,循环文件中的行,并打印包含该数组元素的任何值。然后移动到数组中的下一个元素并重复该过程

下面是到目前为止我的代码,但它似乎没有做任何事情。我不知道我想做的是否可能。任何帮助都将不胜感激

use strict;
use warnings; 

my $keywords= shift;
my $data= shift;

#reading in keywords file and storing in array
open (FH, "< $keywords");
my @keywords= <FH>;
close FH;

# now I want to iterate over the array and for each element loop through
# the datafile checking if the element exists in the line

open (DATAFILE, "< $data");
for my $element (@keywords) {
    for my $line (<DATAFILE>) {
        if ($line =~ /\Q$element\E/) {
            print $line;
        }
    }
}
close DATAFILE;
使用严格;
使用警告;
我的$keywords=shift;
我的$data=shift;
#读取关键字文件并存储在数组中
开放式(FH,“<$keywords”);
我的@keywords=;
关闭FH;
#现在我想迭代数组,并对每个元素循环
#检查行中是否存在元素的数据文件
打开(数据文件“<$data”);
对于我的$element(@keywords){
对于我的$行(){
如果($line=~/\Q$element\E/){
打印$行;
}
}
}
关闭数据文件;

首先,您应该始终检查您的文件打开是否成功,如果没有成功,请进行适当的投诉

open (FH, "< $keywords") or die "Failed to open $keywords: $!";
# ...
open (DATAFILE, "< $data") or die "Failed to open $data: $!";
第三,在您第一次通过
$element
循环读取数据文件之后,您就到了文件的末尾,在连续的
$element
循环中再次读取数据文件将立即返回。最快的修复方法是添加
seek数据文件,0,0
$element
循环的底部。这会将文件指针移回文件的开头,以便您可以再次读取它

最后,如果您给出了这两个文件的内容以及您希望脚本生成的输出的示例,这将非常有用

另一个调试提示:如果我不明白为什么我没有得到我期望的所有匹配项,我会添加如下打印语句:

for my $element (@keywords) {
    print "Starting to search for <$element>\n";
    for my $line (<DATAFILE>) {
        print "Examining line <$line>\n";
        # ...
    }
}
我的$element(@keywords)的
{
打印“开始搜索\n”;
对于我的$行(){
打印“检查行\n”;
# ...
}
}

这将在
$element
中显示换行符,并且您也不会在第一次通过文件后看到
检查行。

首先,您应该始终检查文件打开是否成功,如果没有成功,请进行适当的投诉

open (FH, "< $keywords") or die "Failed to open $keywords: $!";
# ...
open (DATAFILE, "< $data") or die "Failed to open $data: $!";
第三,在您第一次通过
$element
循环读取数据文件之后,您就到了文件的末尾,在连续的
$element
循环中再次读取数据文件将立即返回。最快的修复方法是添加
seek数据文件,0,0
$element
循环的底部。这会将文件指针移回文件的开头,以便您可以再次读取它

最后,如果您给出了这两个文件的内容以及您希望脚本生成的输出的示例,这将非常有用

另一个调试提示:如果我不明白为什么我没有得到我期望的所有匹配项,我会添加如下打印语句:

for my $element (@keywords) {
    print "Starting to search for <$element>\n";
    for my $line (<DATAFILE>) {
        print "Examining line <$line>\n";
        # ...
    }
}
我的$element(@keywords)的
{
打印“开始搜索\n”;
对于我的$行(){
打印“检查行\n”;
# ...
}
}

这将在
$element
中显示换行符,并且您也不会在第一次通过文件后看到
检查行。

此程序对输入文件进行一些假设(例如,关键字文件仅包含一个单词,而不包含包含空格的短语)但这可能是实现目标的最快、最方便的方式

关键字文件中的关键字是唯一的,并按长度降序排序(这样当字符串是
offer
时,就找不到
off
),所有非单词字符都使用
quotemeta
进行转义,以便逐字匹配,而不是作为转义序列的一部分

然后构建一个正则表达式模式,以便优化关键字搜索(因为版本5.10,Perl正则表达式引擎为备选方案列表构建了一个

还有一个问题,比如说,如果
que
是一个关键字,但
古董
不是,那么搜索将返回假阳性。通过明智地使用单词边界正则表达式模式
\b
,它可以得到改进,但这会带来新的问题,例如如果
符号
是一个关键字,而
重新符号
不是,那么搜索将再次返回假阳性。这类问题对单个数据集非常敏感,解决方案不能以与所列假设相同的方式概括

use strict;
use warnings;
use 5.010;
use autodie;

my ($keyword_file, $data_file) = @ARGV;

my $re = do {
  open my $fh, '<', $keyword_file;
  my %kw;
  /(\S+)/ and ++$kw{$1} while <$fh>;
  join '|', map quotemeta, sort { length $b <=> length $a } keys %kw;
};
$re = qr/$re/;

open my $fh, '<', $data_file;
/$re/ and print while <$fh>;
使用严格;
使用警告;
使用5.010;
使用自动模具;
我的($keyword\u file,$data\u file)=@ARGV;
我的$re=do{

打开我的$fh,“这个程序对输入文件做了一些假设(例如,关键字文件只包含一个单词,不包含包含空格的短语),但这可能是实现目标的最快和最方便的方法

关键字文件中的关键字是唯一的,并按长度降序排序(这样当字符串是
offer
时,就找不到
off
),所有非单词字符都使用
quotemeta
进行转义,以便逐字匹配,而不是作为转义序列的一部分

然后构建一个正则表达式模式,以便优化关键字搜索(因为版本5.10,Perl正则表达式引擎为备选方案列表构建了一个

还有一个问题,比如说,如果
que
是一个关键字,但
古董
不是,那么搜索将返回一个假阳性。明智地使用单词边界regex模式
\b
,可以改善这一点,但这带来了新的问题,例如
符号
是否是一个关键字,但
重新符号
i如果不是,则搜索将再次返回假阳性