use strict;
use warnings;
my %result_hash = ();
my %final_hash = ();
Compare_results();
foreach my $key (sort keys %result_hash ){
print "$key \n";
print "$result_hash{$key} \n";
}
sub Compare_results
{
while ( <DATA> )
{
my($instance,$values) = split /\:/, $_;
$result_hash{$instance} = $values;
}
}
__DATA__
1:7802315095\d\d,7802315098\d\d;7802025001\d\d,7802025002\d\d,7802025003\d\ d,7802025004\d\d,7802025005\d\d,7802025006\d\d,7802025007\d\d
2:7802315095\d\d,7802025002\d\d,7802025003\d\d,7802025004\d\d,7802025005\d\d,7802025006\d\d,7802025007\d\d
输出
1
7802315095\d\d,7802315098\d\d;7802025001\d\d,7802025002\d\d,7802025003\d\d,7802025004\d\d,7802025005\d\d,7802025006\d\d,7802025007\d\d
2
7802315095\d\d,7802025002\d\d,7802025003\d\d,7802025004\d\d,7802025005\d\d,7802025006\d\d,7802025007\d\d
Iam尝试获取每个键的值并再次尝试从结果哈希中分割逗号分隔值,如果我在任何值中找到分号,我希望将左侧和右侧值存储在单独的哈希键中。
如下所示
1.#split the value of result_hash{$key} again by , and see whether any chunk is seperated by ;
2. #every chunk without ; and value on left with ; should be stored in
@{$final_hash{"eto"}} = ['7802315095\d\d','7802315098\d\d','7802025002\d\d','7802025003\d\d','7802025004\d\d','7802025005\d\d','7802025006\d\d','7802025007\d\d'] ;
3.#Anything found on the right side of ; has to be stored in
@{$final_hash{"pro"}} = ['7802025001\d\d'] ;
有没有办法可以处理子程序中的所有内容?我可以使代码更简单吗
更新:
我尝试在一次拍摄中分割字符串,但它只是用分号选择值并忽略所有内容
foreach my $key (sort keys %result_hash ){
# print "$key \n";
# print "$result_hash{$key} \n";
my ($o,$t) = split(/,|;/, $result_hash{$key});
print "Left : $o \n";
print "Left : $t \n";
#push @{$final_hash{"eto"}}, $o;
#push @{$final_hash{"pro"}} ,$t;
}
}
我帮助后的更新代码
sub Compare_results
{
open my $fh, '<', 'Data_File.txt' or die $!;
# split by colon and further split by , and ; if any (done in insert_array)
my %result_hash = map { chomp; split ':', $_ } <$fh> ;
foreach ( sort { $a <=> $b } (keys %result_hash) )
{
($_ < 21)
? insert_array($result_hash{$_}, "west")
: insert_array($result_hash{$_}, "east");
}
}
sub insert_array()
{
my ($val,$key) = @_;
foreach my $field (split ',', $val)
{
$field =~ s/^\s+|\s+$//g; # / turn off editor coloring
if ($field !~ /;/) {
push @{ $file_data{"pto"}{$key} }, $field ;
}
else {
my ($left, $right) = split ';', $field;
push @{$file_data{"pto"}{$key}}, $left if($left ne '') ;
push @{$file_data{"ero"}{$key}}, $right if($right ne '') ;
}
}
}
由于
答案 0 :(得分:2)
更新在最后添加了两遍正则表达式
系统地进行,逐步分析字符串。事实上,您需要连续拆分和特定的分离规则,这使得一次性操作变得难以处理。最好有一个明确的方法而不是怪物陈述。
use warnings 'all';
use strict;
use feature 'say';
my (%result_hash, %final_hash);
Compare_results();
say "$_ => $result_hash{$_}" for sort keys %result_hash;
say '---';
say "$_ => [ @{$final_hash{$_}} ]" for sort keys %final_hash;
sub Compare_results
{
%result_hash = map { chomp; split ':', $_ } <DATA>;
my (@eto, @pro);
foreach my $val (values %result_hash)
{
foreach my $field (split ',', $val)
{
if ($field !~ /;/) { push @eto, $field }
else {
my ($left, $right) = split ';', $field;
push @eto, $left;
push @pro, $right;
}
}
}
$final_hash{eto} = \@eto;
$final_hash{pro} = \@pro;
return 1; # but add checks above
}
这里有一些效率低下,没有错误检查,但方法很简单。如果您的输入不是很小,请更改以上内容逐行处理,您清楚知道该怎么做。它打印
1 => ... (what you have in the question) --- eto => [ 7802315095\d\d 7802315098\d\d 7802025002\d\d 7802025003\d\ d ... pro => [ 7802025001\d\d ]
请注意,您的数据有一个松散的\d\ d
。
我们不需要为此构建整个哈希%result_hash
,而只需要在:
之后选择该行的一部分。我离开了哈希,因为它被声明为全局,所以你可能想要它。如果事实上不需要它本身就可以简化
sub Compare_results {
my (@eto, @pro);
while (<DATA>) {
my ($val) = /:(.*)/;
foreach my $field (split ',', $val)
# ... same
}
# assign to %final_hash, return from sub
}
感谢ikegami发表评论。
出于好奇心的缘故,这里有正则表达式的两次传递
sub compare_rx {
my @data = map { (split ':', $_)[1] } <DATA>;
$final_hash{eto} = [ map { /([^,;]+)/g } @data ];
$final_hash{pro} = [ map { /;([^,;]+)/g } @data ];
return 1;
}
使用否定字符类,,
,选择不是;
或[^,;]
的所有字符。所以这是第一个,从左到右。它在全球范围内/g
执行此操作,因此它会不断浏览字符串,收集“,
或;
左侧的所有字段。然后它会欺骗一点,挑选[^,;]
右边的所有;
。 map
用于为所有数据行执行此操作。
如果需要%result_hash
,请构建而不是@data
,然后使用my @values = values %hash_result
从中提取值,并使用@values
提供地图。
或者,逐行划分(再次,您可以构建%result_hash
而不是直接使用$data
)
my (@eto, @pro);
while (<DATA>) {
my ($data) = /:(.*)/;
push @eto, $data =~ /([^,;]+)/g;
push @pro, $data =~ /;([^,;]+)/g;
}