2009-09-29 8 views
2

내가 통해 실행과 같은 다양한 데이터 요소 잡기 위해 Perl 스크립트 쓰고 있어요 :Perl에서 고정 너비 형식의 열을 추출하려면 어떻게해야합니까?

1253592000 
1253678400     86400     6183.000000 
1253764800     86400     4486.000000 
1253851200 36.000000  86400    10669.000000 
1253937600 0.000000  86400     9126.000000 
1254024000 0.000000  86400     2930.000000 
1254110400 0.000000  86400     2895.000000 
1254196800 0.000000        8828.000000 

나는이 텍스트 파일 아무 문제의 각 라인을 잡아 수 있습니다.

정규식을 사용하여 각 필드를 가져와야합니다. 변수에 줄이 생기면 ($ 줄 등) 구분 기호가 다른데도 각 필드를 어떻게 잡아 자신의 변수에 넣을 수 있습니까?

+1

구분 기호가 무엇인지 조금 더 구체적으로 알려주시겠습니까? –

+0

@Paul : 그게 문제입니다. 이 출력은 응용 프로그램 (splunk)에 의해 생성됩니다.구분 기호는 설정할 수 없으며 각 열 사이에 공백 문자가 두 개인 것처럼 보입니다. 그러나 그 너머에있는 공백이 있습니다. – Greg

+3

@ 그렉 : 이것은 정말로 "구분 된"파일처럼 보이지 않습니다. 이들은 고정 너비 열입니다. 아래의 FM 솔루션은 실제로 이것을 분석하는 가장 깨끗한 방법입니다. –

답변

-1

줄을 나눌 수 있습니다. 단락 기호는 공백 문자로 보입니다. 다음과 같은 순서로 작업 할 수 있습니다.

@line = split(" ", $line); 

모든 공백과 일치합니다. 그런 다음 경계 검사를 수행하고 $ line [0], $ line [1] 등을 통해 각 필드에 액세스 할 수 있습니다.

분할은 문자열이 아닌 구분 기호로 정규 표현식을 사용할 수도 있습니다.

@line = split(/\s+/, $line); 

이것은 동일한 일을 할 수 있습니다.

+5

나는 그가 고정 너비 인코딩에 대해 이야기하고 있다고 생각한다. 이 방법을 사용 –

+0

는 - 큰 출력을 작동합니다 시간 : 1,253,592,000 Livereporter : 스팬 : Bcreporter : 시간 : 1,253,678,400 Livereporter : 86400 스팬 : 6183.000000 Bcreporter : 시간 : 1,253,764,800 Livereporter : 86400 스팬 : 4486.000000 Bcreporter : 시간 : 1,253,851,200 Livereporter : 36.000000 스팬 : 86400 Bcreporter : 10669.000000 시간 : 1,253,937,600 Livereporter : 0.000000 스팬 : 86400,451,515,Bcreporter : 9126.000000 시간 : 1,254,024,000 Livereporter : 0.000000 스팬 : 86400 Bcreporter : 2930.000000 시간 : 1,254,110,400 Livereporter : 0.000000 스팬 : 86400 Bcreporter : 2895.000000 시간 : 1,254,196,800 Livereporter : 0.000000 스팬 : 8828.000000 – Greg

+1

당신 일부 필드가 비어 있기 때문에 공백으로 분리 할 수 ​​없습니다. 이 작업을 수행 할 때 열 순서가 손실됩니다. –

-2

고정 폭 단락 문자는 다음과 같이 수행 할 수 있습니다

my @cols; 
my %header; 
$header{field1} = 0; // char position of first char in field 
$header{field2} = 12; 
$header{field3} = 15; 

while(<IN>) { 

    print chomp(substr $_, $header{field2}, $header{field3}); // value of field2 


} 

내 펄 그래서 내가 거기에 구문 오류가 확신 아주 녹슨입니다. 그러나 그것의 요지입니다. 모든 필드가 같은 고정 폭 공백으로 포맷하는 경우

+1

왜 너는 그렇게 복잡해? 그게 지문이 뭐라고 생각하니? 힌트를 얻으려면 chomp 문서를 참조하십시오. 너무 심하지 않아도 되겠지만, 한번도 해보지도 않고 실행 해 본 적이없는 것을 보여 주거나 추측한다면 경험이 많은 사람이 대답 할 때까지 기다려야합니다. –

-1

, 당신은 다음과 같은 split 사용할 수 있습니다

@array = split/{1,N}/, $line; 

N이 필드와 함께입니다. 이렇게하면 빈 필드마다 공백이 생깁니다.

+0

나는 그것이 당신이 생각하는 것을 그렇게 생각하지 않는다. 한 줄에는 논리에 하나, 구문에 하나씩 두 가지 주요 오류가 있습니다. –

+0

@brian d foy : 고마워요. 품질이 낮은 답변을 드려 죄송합니다. 어쨌든,'unpack' 솔루션이 더 좋습니다. –

13

이 예제는 공백을 구분 기호 (split) 또는 고정 열 레이아웃 (unpack)으로 파싱하는 방법을 보여줍니다. unpack으로 대문자 (A10 등)를 사용하면 공백이 제거됩니다. 참고 : brian d foy가 지적했듯이 필드 위치 정보가 손실 될 수 있기 때문에 필드가 누락 된 상황 (예 : 두 번째 데이터 행)에서는 split 접근 방식이 제대로 작동하지 않습니다. unpack은 귀하의 데이터를 오해하지 않는 한, 여기로 갈 수있는 방법입니다.

use strict; 
use warnings; 

while (my $line = <DATA>){ 
    chomp $line; 
    my @fields_whitespace = split m'\s+', $line; 
    my @fields_fixed = unpack('a10 a10 a12 a28', $line); 
} 

__DATA__ 
1253592000             
1253678400     86400     6183.000000 
1253764800     86400     4486.000000 
1253851200 36.000000  86400    10669.000000 
1253937600 0.000000  86400     9126.000000 
1254024000 0.000000  86400     2930.000000 
1254110400 0.000000  86400     2895.000000 
1254196800 0.000000        8828.000000 
+0

샘플 데이터의 레이아웃이 주어진 경우, 압축을 해제하려면 +1 – Hobo

+3

모두가 Perl에 팩이 있다는 것을 잊어 버리지 만, 정말 편리합니다. 필자는 Effective Perl Programming의 다음 판을 위해이 장을 편집하고있었습니다. :) –

+1

'split m '\ s +''가 더 잘 강조 될 것입니다. –

0

나는 열 이름과 형식의 확실 해요하지만 당신은 Text::FixedWidth

use strict; 
use warnings; 
use Text::FixedWidth; 

my $fw = Text::FixedWidth->new; 
$fw->set_attributes(
    qw(
     timestamp undef %10s 
     field2 undef %10s 
     period undef %12s 
     field4 undef %28s 
     ) 
); 

while (<DATA>) { 
    $fw->parse(string => $_); 
    print $fw->get_timestamp . "\n"; 
} 

__DATA__ 
1253592000 
1253678400     86400     6183.000000 
1253764800     86400     4486.000000 
1253851200 36.000000  86400    10669.000000 
1253937600 0.000000  86400     9126.000000 
1254024000 0.000000  86400     2930.000000 
1254110400 0.000000  86400     2895.000000 
1254196800 0.000000        8828.000000 
3

사용 my module DataExtract::FixedWidth를 사용하여 원하는대로이 조리법을 조정할 수 있어야한다. perl의 고정 너비 열 (fixed width column)을 사용하기위한 가장 완전한 기능을 갖춘 잘 테스트 된 도구입니다. 이것이 충분히 빠르지 않으면 unpack_string을 전달할 수 있고 경계의 발견 적 발견의 필요성을 제거 할 수 있습니다.

#!/usr/bin/env perl 
use strict; 
use warnings; 
use DataExtract::FixedWidth; 
use feature ':5.10'; 

my @rows = <DATA>; 
my $de = DataExtract::FixedWidth->new({ 
    heuristic => \@rows 
    , header_row => undef 
}); 

say join ('|', @{$de->parse($_)}) for @rows; 

    --alternatively if you want header info-- 

my @rows = <DATA>; 
my $de = DataExtract::FixedWidth->new({ 
    heuristic => \@rows 
    , header_row => undef 
    , cols => [qw/timestamp field2 period field4/] 
}); 

use Data::Dumper; 
warn Dumper $de->parse_hash($_) for @rows; 

__DATA__ 
1253592000 
1253678400     86400     6183.000000 
1253764800     86400     4486.000000 
1253851200 36.000000  86400    10669.000000 
1253937600 0.000000  86400     9126.000000 
1254024000 0.000000  86400     2930.000000 
1254110400 0.000000  86400     2895.000000 
1254196800 0.000000        8828.000000 
+0

필자는 과거에이 모듈을 사용해 왔으며 열 감지가 매끄 럽습니다. – Demosthenex