2016-09-21 53 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