我有一个文件,其中 4 列包含约 9 万行文本。
col1 col2 col3 value1
...
col1 col2 col3 value90000
第二个文件包含约 200 行,每一行对应于较大文件第 4 列中的一个值。
value1
value2
...
value200
我想从较小的文件中读取每个值,在较大的文件中找到相应的行,然后返回该行。我编写了一个 perl 脚本,它将小文件中的所有值放入一个数组中,然后使用每个值作为正则表达式来迭代该数组,以搜索较大的文件。经过一些调试后,我觉得它几乎可以工作,但我的脚本只返回与数组的最后一个元素相对应的行。
这是我的代码:
open my $fh1, '<', $file1 or die "Could not open $file1: $!";
my @array = <$fh1>;
close $fh1;
my $count = 0;
while ($count < scalar @array) {
my $value = $array[$count];
open my $fh2, '<', $file2 or die "Could not open $file2: $!";
while (<$fh2>) {
if ($_ =~ /$value/) {
my $line = $_;
print $line;
}
}
close $fh2;
$count++;
}
这仅返回:
col1 col2 col3 value200
我可以让它打印数组的每个值,所以我知道它正在正确迭代,但它并没有按照我的预期使用每个值来搜索更大的文件。我还可以将数组中的任何值插入 $value
变量并返回相应的行,这样我就知道这些行在那里。我怀疑我的错误可能与以下任一有关:
- 数组元素中的换行符,因为除最后一个元素之外的所有元素都有换行符。我尝试过
chomp
但得到了相同的结果。
或
- 与我处理打开/关闭第二个文件的方式有关。我尝试过移动或删除
close
命令,但这要么会破坏代码,要么没有帮助。
最佳答案
您应该只读取 90k 行文件一次,并按照每行的第四列检查另一个文件中的每个值,而不是较小文件的每行读取整个大文件一次:
#!usr/bin/env perl
use warnings;
use strict;
use feature qw/say/;
my ($file1, $file2) = @ARGV;
# Read the file of strings to match against
open my $fh1, '<', $file1 or die "Could not open $file1: $!";
my %words = map { chomp; $_ => 1 } <$fh1>;
close $fh1;
# Process the data file in one pass
open my $fh2, '<', $file2 or die "Could not open $file2: $!";
while (my $line = <$fh2>) {
chomp $line;
# Only look at the fourth column
my @fields = split /\s+/, $line, 4;
say $line if exists $words{$fields[3]};
}
close $fh2;
请注意,这使用与最后一列的直接字符串比较(通过哈希键查找)而不是正则表达式匹配 - 您的示例数据看起来就是所需要的。如果您使用实际的正则表达式,请告诉我,我将更新答案。
你的代码看起来确实应该可以工作,只是效率非常低。事实上,在调整示例数据以便多行匹配之后,它确实为我打印出了多行。
关于arrays - 多次迭代一个文件,每次查找一个正则表达式并返回一行(perl),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64378358/