2016-09-21 51 views
2
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 

输出处理嵌套的分隔符在Perl

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.#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)标量,所以你只能得到分割后的前两个元素。) – zdim

+0

我编辑了你的添加 - 将长注释移动到它自己的行,所以不必滚动阅读它,并通过正则表达式添加了一个评论'#/ ...',这个编辑器关闭了错误的红色着色。 (它经常这样做 - 在一个正则表达式之后,一切都变成红色。)如果你不喜欢这个,请恢复更改 - 点击我的用户名上面的“编辑(时间)”,你会看到修订版本,每个版本都有按钮。其中一个说“回滚”,点击你想要回滚的修订版本。 – zdim

+0

@zdim:你会让我知道如何分割有两个分隔符的数据:1,2,3,4,5,6,7; 8,9,10,11,12,我想存储所有的东西之后;在一个数组中,在另一个数组中。请用一杆分裂功能帮助我。 O/P array1 = [1,2,3,4,5,6,7]和array2 = [8,9,10,11,12] – LearningCpp

回答

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; 
} 
+0

@ LearningCpp我更新了答案 - 完成了完整程序的代码,用数据进行了测试,并添加了一些评论。 – zdim

+0

谢谢@zdim,我已经使用了你最后一块代码,但是它附加了一个额外的\ \ d(ie \\ d),你能否解释一下map {chomp;(split':',$ _)[1 ]};我添加了chomp来清除空容器 – LearningCpp

+0

@LearningCpp这很奇怪 - 它不会将它添加到我的测试中(我发布的输出被复制到终端上),因为它不应该这样做。这是正则表达式的输出。该行如下。它“换取”换行符。然后它按':'分割,产生两个字段。 '地图'是这样的,它为每一行都做了这个,并且整个列表被发送。所以这些是成对的,你可以直接把它分配给一个散列。这是合法的:'my%h =(1,'one',2,'two');'它将它们配对,'key =>值,...'分配给散列的一个非常好的方法。 – zdim