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

출력펄에 중첩 구분 기호를 처리

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 '') ; 
    } 
    } 
    } 
,451,515,

감사 말


에서

+0

좋은 생각 (다시, 당신은 대신 직접 $data을 복용 %result_hash을 구축 할 수 있습니다)하지만, 당신도'/ [,]에 분할하는 경우 /'어떻게 알 수 있습니까 어떤 것이 "올바른"것입니까 (';'의 오른쪽)? ','또는';'사이의 모든 필드 목록을 반환합니다. (당신이 썼던 것은 두개의 스칼라에리스트를 할당하기 때문에 처음 두 개의 원소 만 나눕니다.) – zdim

+0

추가 된 내용을 편집했습니다 - 긴 주석을 자체 라인으로 옮겨서 스크롤 할 필요가 없습니다 그리고 편집기에서 잘못된 빨강 색을 끄는 regex에 의한'#/...'주석을 추가했습니다. (자주 - 정규 표현식이 모두 붉은 색으로 변한 후에) 변경 사항을 되돌리려면 - 사용자 이름 위의 "편집 (시간)"을 클릭하면 각각의 버튼과 함께 수정본이 보일 것입니다. 그 중 하나가 "롤백"이라고 말하면 롤백하려는 버전을 클릭하십시오. – 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] and array2 = [8,9,10,11,12] – LearningCpp

답변

2

업데이트   추가 된 두 단계 정규식, 그냥, 체계적으로 진행 단계별로 문자열 단계를 분석 할 수 있습니다. 연속 된 분할과 특정 분리 규칙이 필요하다는 사실 때문에 한 번에 처리하기가 쉽지 않습니다. 괴물 성명서보다 명확한 방법이 더 좋습니다.

여기에는 비효율적이며 오류 검사는 없지만 방법은 간단합니다. 입력 내용이 작지만 조금이라도 다르다면 위의 내용을 한 줄씩 처리하도록 변경하십시오. 그것은 인쇄합니다

 
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를 구축하지만 : 후 라인의 일부를 선택해야 할 필요가 없습니다. 전역으로 선언되었으므로 해시를 남겼습니다. 따라서 해시를 가질 수 있습니다. 이 사실 자체에 필요하지 않은 경우이 의견 ikegami

sub Compare_results { 
    my (@eto, @pro); 
    while (<DATA>) { 
     my ($val) = /:(.*)/; 
     foreach my $field (split ',', $val) 
     # ... same 
    } 
    # assign to %final_hash, return from sub 
} 

감사를 단순화합니다.그냥 호기심을 위하여


는 여기이는 부정 문자 클래스, [^,;]를 사용하지 , 또는 ; 모든 문자를 선택합니다 정규식

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으로지도를 공급 필요합니다.

또는 라인으로 점선

my (@eto, @pro); 
while (<DATA>) { 
    my ($data) = /:(.*)/; 
    push @eto, $data =~ /([^,;]+)/g; 
    push @pro, $data =~ /;([^,;]+)/g; 
} 
+0

@ LearningCpp 나는 해답을 업데이트했다. 코드를 전체 프로그램으로 완성하고 데이터로 테스트 한 다음 몇 가지 코멘트를 추가했다. – zdim

+0

@ zdim, 고마워요, 마지막 코드 조각을 사용했는데 추가 \를 \ d (예 : \\ d)로 추가했습니다. 또한지도 {chomp; (split ':', $ _) [1 ]}; 나는 빈을 제거하기위한 chomp를 추가했다. – LearningCpp

+0

@LearningCpp 이상하게 들리지만, 그것은 필자의 테스트에서 추가하지 않았다. 그것은 정규 표현식에 대한 동일한 출력입니다. 그 줄은 다음과 같습니다. 그것은 개행을'chomp'합니다. 그런 다음':'로 분할하여 두 개의 필드를 생성합니다. 'map'은 모든 행에 대해 이렇게하기 때문에 전체 목록이 전송됩니다.그래서 이것들은 쌍이며, 이것을 해시에 직접 할당 할 수 있습니다. 이것은 합법적입니다 :'my % h = (1, 'one', 2, 'two');'그것들을 쌍으로 묶습니다, key => value, ...'해쉬에 할당하는 아주 좋은 방법입니다. – zdim

관련 문제