我的正则表达式只匹配一些表达式。当我在regex101.com上测试表达式时它运行得很好......我的代码可能出现什么问题?
提前感谢您的帮助。
示例文件,“surfacecoating”:
[
('amino acids', 339, 350),
('copper', 71, 77),
('copper', 0, 6),
('copper', 291, 297),
('amino acids', 119, 130)]
什么Dumper打印出这个文件(注意不返回前3个匹配):
'surfacecoating' => {
'copper' => '291',
'amino acids' => '119'
},
代码:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
determine_cde_instances();
sub determine_cde_instances {
my %cdeinstances;
my %cde_instances;
my $dir = "/results/CDE";
opendir my $dh, $dir or die "Can't open $dir: $!";
while (my $file = readdir($dh)) {
next if ($file =~ m/^\./);
next if -d $file;
open my $fh, '<', "$dir/$file" or die "Can't open $dir/$file: $!";
while (my $line = <$fh>)
{
if (my ($instance) = $line =~ m/'(.*?)', (.*?), /)
{
my $instance = $1;
my $pos = $2;
$cde_instances{$file}{$instance} = $pos;
}
}
close $fh;
}
close $dh;
print Dumper(\%cde_instances);
return %cde_instances;
}
答案 0 :(得分:2)
您使用密钥$instance
将信息存储在hashref中,但数据中的某些密钥在多行中是相同的。因此,密钥'copper'
会被重复覆盖,最后只会出现最后一次。 'amino acids'
也是如此。
由于这些关键字要成为哈希键重复,因此您无法使用直接哈希。您需要提出不同的数据结构,具体取决于您需要对数据执行的操作。
一个合理的想法是使用一个数组,也许是一个带有hashrefs的数组,每对一个
if ($line =~ m/'(.*?)', (.*?), /)
{
my %instance_pos = ($1, $2);
push @{$cde_instances{$file}}, \%instance_pos;
}
此处,散列$file
中的每个键%cde_instances
都有一个arrayref作为其值,为每个实例-pos对提供hashrefs。当然,还有其他选择,这是一个更好的例子。
这也可以写成
if (my %instance_pos = $line =~ m/'(.*?)', (.*?), /) {
push @{$cde_instances{$file}}, \%instance_pos;
}
或只是
if ($line =~ m/'(.*?)', (.*?), /) {
push @{$cde_instances{$file}}, {$1, $2};
}
如果您需要检查/验证捕获,请从正则表达式分配两个变量。
通过上述更改并使用use Data::Dump qw(dd);
打印我得到
{ "data.txt" => [ { "amino acids" => 339 }, { copper => 71 }, { copper => 0 }, { copper => 291 }, { "amino acids" => 119 }, ], }
请注意,正则表达式后面的数字不会被正则表达式捕获。我认为这是故意的。请澄清它不是这样。