2014-10-11 4 views
3

저는 Perl에 익숙하지 않아 구조화 된 텍스트 파일을 성공적으로 구문 분석 할 Perl 스크립트를 작성하는 데 엄청난 어려움을 겪고 있습니다.Perl에서 구조화 된 텍스트 파일 구문 분석하기

name: 
    John Smith 
occupation: 
    Electrician 
date of birth: 
    2/6/1961 
hobbies: 
    Boating 
    Camping 
    Fishing 

등등 :

나는 다음과 같이 파일의 컬렉션을 가지고있다. 필드 이름에는 항상 콜론이오고 해당 필드와 관련된 모든 데이터는 항상 단일 탭 (\ t)으로 들여 쓰기됩니다.

내가 직접이 같은 필드 이름을 가진 필드의 내용을 연결합니다 해시를 만들 싶습니다 : 그 라인을 따라

$contents{$name} = "John Smith" 
$contents{$hobbies} = "Boating, Camping, Fishing" 

또는 무언가를.

지금까지 모든 필드 이름을 자체적으로 해시로 가져올 수 있었지만 필드 데이터를 해시에 잘 저장 될 수있는 형식으로 변경하는 행운은 없었습니다. 분명한 개행/개조 뉴 라인 다음에 탭이 작동하지 않습니다. (나는 다소 순진하게 시도했습니다). 나는 또한 파일에서 라인의 중복 배열을 생성하고 그것을 사용하여 필드 경계가 어디인지 알아내는 조잡한 미리보기를 시도했지만 메모리 소비면에서 그리 좋지는 않다.

FWIW, 현재 필자는 줄 단위로 파일을 검토하고 있지만 이것이 최선의 솔루션이라고 완전히 확신하지는 않습니다. 이 구문 분석을 간단하게 수행 할 수있는 방법이 있습니까?

답변

5

줄 단위로 파일을 읽는 것이 좋습니다. 여기 배열 참조의 해시를 생성합니다. 이것은 하나의 파일을 읽는 방법입니다. 이 방법으로 각 파일을 읽고 어레이의 해시를 배열 해시의 해시에 넣을 수 있습니다.

#!/usr/bin/perl 

use strict; 
use warnings; 
use Data::Dumper; 

my %contents; 
my $key; 
while(<DATA>){ 
    chomp; 
    if (s/:\s*$//) { 
     $key = $_; 
    } else { 
     s/^\s+//g; # remove extra whitespace 
     push @{$contents{$key}}, $_; 
    } 
} 
print Dumper \%contents; 

__DATA__ 
name: 
    John Smith 
occupation: 
    Electrician 
date of birth: 
    2/6/1961 
hobbies: 
    Boating 
    Camping 
    Fishing 

출력 :

$VAR1 = { 
      'occupation' => [ 
          'Electrician' 
          ], 
      'hobbies' => [ 
          'Boating', 
          'Camping', 
          'Fishing' 
         ], 
      'name' => [ 
         'JohnSmith' 
        ], 
      'date of birth' => [ 
           '2/6/1961' 
           ] 
     }; 
+2

그리고 그 어려운 유효한 YAML 파일로 변환하기 's/\ s + // g;로 모든 여분의 공백을 제거하지 않는 것이 가장 좋습니다 - 이름에 유용합니다! ';)' –

+2

@ialarmedalien은 Miller가 선행 공백 문자로 그것을 업데이트 한 것처럼 보입니다. 틀림없이 이름이 맞아요. 잘 부탁드립니다. 필요한 경우 요소를 처리 할 수있는 위치를 보여주기 위해 무언가를 던지고 싶었습니다! – chilemagic

+0

이것은 정확히 내가 필요로하는 것입니다 - 그것이 그렇게 될 것이라고 생각했던 것보다 훨씬 쉽습니다. 감사! – MARS

2

이 텍스트 파일이 실제로 YAML에 매우 가깝습니다. 당신은 당신이 YAML을 사용할 수있는 YAML 파일이 있으면

이 :: 작은 또는 다른 모듈을 구문 분석, 청소기 코드로 연결 : 아마

#!/usr/bin/perl 
use strict; 
use warnings; 

use YAML::Tiny; 
use Data::Dumper; 

convert('./data.yaml', 'output.yaml'); 
parse('output.yaml'); 

sub parse { 
    my $yaml = shift; 
    my $yamlobj = YAML::Tiny->read($yaml); 

    my $name = $yamlobj->[0]->{name}[0]; 
    my $occ  = $yamlobj->[0]{occupation}[0]; 
    my $birth = $yamlobj->[0]{'date of birth'}[0]; 
    my $hobbies = $yamlobj->[0]{hobbies}; 

    my $hobbiestring = join ", ", @$hobbies; 

    my $contents = { 
     name  => $name, 
     occupation => $occ, 
     birth  => $birth, 
     hobbies => $hobbiestring, 
    }; 

    print "#RESULT:\n\n"; 
    print Dumper($contents); 
} 

sub convert { 
    my ($input, $output) = @_; 

    open my $infh, '<', $input or die "$!"; 
    open my $outfh, '>', $output or die "$!"; 

    while (my $line = <$infh>) { 
     $line =~ s/^\s+\K$/-/g; 
     print $outfh ($line); 
    } 
} 
관련 문제