perl:正则表达式只匹配一些时间

时间:2017-04-20 20:30:51

标签: regex perl

我的正则表达式只匹配一些表达式。当我在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;
}

1 个答案:

答案 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 },
  ],
}

请注意,正则表达式后面的数字不会被正则表达式捕获。我认为这是故意的。请澄清它不是这样。