我不确定如何正确初始化我的哈希 - 我正在尝试为输入文件中的耦合行中的值创建键/值对。
例如,我的输入如下:
@cluster t.18
46421 ../../../output###.txt/
@cluster t.34
41554 ../../../output###.txt/
我从第1行(@cluster行)中提取t数,并将其与第二行中的输出###。txt相匹配(以46421开头的行)。但是,我似乎无法使用我编写的脚本将这些值放入哈希。
#!/usr/bin/perl
use warnings;
use strict;
my $key;
my $value;
my %hash;
my $filename = 'input.txt';
open my $fh, '<', $filename or die "Can't open $filename: $!";
while (my $line = <$fh>) {
chomp $line;
if ($line =~ m/^\@cluster/) {
my @fields = split /(\d+)/, $line;
my $key = $fields[1];
}
elsif ($line =~ m/^(\d+)/) {
my @output = split /\//, $line;
my $value = $output[5];
}
$hash{$key} = $value;
}
答案 0 :(得分:6)
这是一个好主意,但在$key
块中使用my
创建的if
是一个作用于该块的局部变量,掩盖全球$key
。在if
块内,符号$key
与您提前声明的那个没有任何关系。请参阅my in perlsub
。
$key
完成if
后,本地if
超出范围,并且在$key
块之外不存在。全局if
在$value
之后再次可用,在循环中的其他位置可见,但未定义,因为它从未被分配到。 elsif
块中的my
也是如此。
只需将$key = ...
声明放入循环中,从而分配给那些全局变量(如预期的那样?)。因此,$value = ...
和input.txt
会正确分配哈希值。
注意 - 这是关于如何正确地获得该哈希分配。我不知道您的实际数据是如何看的以及该行是否被正确解析。这是一个玩具$value = $output[3];
@cluster t.1 1111 ../../../output1.1.txt/ @cluster t.2 2222 ../../../output2.2.txt/
我选择第4个字段而不是第6个字段print "$_ => $hash{$_}\n" for keys %hash;
,然后添加
split
循环后。这打印
1 => output1.1.txt 2 => output2.2.txt
我不确定这是否是你想要的,但是哈希建立得很好。
关于解析
中工具选择的评论您可以解析数字的行,使用split
的属性来捕获分隔符。这很简洁,但在某种意义上它颠倒了它的主要目的,即从模式中分离出来的其他组件。因此,它可能使代码的目的有点复杂,并且您还必须非常精确地索引以检索您需要的内容。
不是使用if ($line =~ m/^\@cluster/) {
($key) = $line =~ /t\.(\d+)/;
}
elsif ($line =~ m/^(\d+)/) {
($value) = $line =~ m|.*/(\w+\.txt)|;
}
$hash{$key} = $value if defined $key and defined $value;
来提取由正则表达式给出的分隔符本身,为什么不用正则表达式提取它?这也意味着清晰。例如,输入
@cluster t.10 has 4319 elements, 0 subclusters 37652 ../../../../clust/output43888.txt 1.397428
解析可以作为
t\.
添加\.txt
和\d+
以更精确地指定目标。如果目标字符串不能确定具有该精确形式,则只需捕获/
,在第二种情况下,在m|^\d+.*/(\S+)|
之后的所有非空格,例如.*
。我们使用/
的贪婪,它将所有与之后的事物(一个/
)相匹配,从而一直到最后{{1} }}
然后您还可以将其缩减为每行的单个正则表达式,例如
if ($line =~ m/^\@cluster\s+t\.(\d+)/) {
$key = $1;
}
elsif ($line =~ m|^\d+.*/(\w+\.txt)|) {
$value = $1;
}
请注意,我已为哈希分配添加了条件。事实上,原始代码在第一次迭代时会分配undef
,因为此时尚未看到$value
。这会在下一次迭代时被覆盖,如果我们之后只打印哈希,我们就不会看到它。对于格式错误的线路等,该条件还可以防止失败的匹配。当然,可以运行更好的检查。