2012-12-19 3 views
1

메시지 정의로 하나의 파일에서 값을 추출하고이를 사용하여 구성 파일을 업데이트하는 펄 스크립트를 작성하고 있습니다.Grep : 다른 파일을 업데이트하기 위해 한 파일에서 데이터를 추출하십시오.

메시지 정의 파일 (ICD.txt) : 예를 들어

FOO_TELEM 메시지가 회원 180

에 범위 -180 90과 경도 범위 -90와 위도했다
MESSAGE: FOO_TELEM 
latitude [-90,90] 
longitude [-180,180] 
MESSAGE: FOO_FREQUENCY 
airPressure [0,50] 
engineSpeed [0,65500] 

구성 파일 (config.txt 파일) : 내가 좋아하는 것

MessageTable 
    Message FOO_TELEM 
     Member latitude DOUBLE End-Member 
     Member longitude DOUBLE End-Member 
    End-Message 
    Message FOO_FREQUENCY 
     Member airPressure ULONG End-Member 
     Member engineSpeed ULONG End-Member 
    End-Message 
    End-MessageTable 

가 upda 할 수 있도록

업데이트 된 구성 파일 (config.txt 파일) :

결과는 같을 것이다 있도록 메시지 정의 파일 (ICD.txt)에 포함 된 제약 조건 값으로 설정 파일 (config.txt 파일)을 테
MessageTable 
    Message FOO_TELEM 
     Member latitude DOUBLE CONSTRAINT -90 90 End-Member 
     Member longitude DOUBLE CONSTRAINT -180 180 End-Member 
    End-Message 
    Message FOO_FREQUENCY 
     Member airPressure ULONG CONSTRAINT 0 50 End-Member 
     Member engineSpeed ULONG CONSTRAINT 0 65500 End-Member 
    End-Message 
    End-MessageTable 

필자는 필요한 결과를 얻기 위해 다양한 형태의 grep을 시도했지만 성공하지 못했습니다. 어떤 제안이라도 대단히 감사하겠습니다. grep, sed 및/또는 perl과 관련된 모든 솔루션에 대해 열려 있습니다.

+0

정규 표현식이 작동합니까? –

답변

2

여기 사진이 있습니다. 열기/닫기 로직을 ​​작성하면 안되기 때문에 내 파일에 DATA을 두 번 사용할 예정입니다.

use strict; 
use warnings; 

my %messages; 
my $current; 
CONSTRAINT: 
while (<DATA>) { 
    last CONSTRAINT if m/^---$/; 
    if (my ($message) = m/^ MESSAGE: \s+ (\S+)/x) { 
     $messages{ $message } = $current = {}; 
    } 
    elsif (my ($name, $min, $max) 
       = m/^ (\w+) \s+ \[ \s* (-?\d+), \s* (-?\d+) \s* \]/x 
     ) { 
     $current->{ $name } = [ $min, $max ]; 
    } 
} 
while (<DATA>) { 
    chomp; 
    if (my ($msg) = m/Message \s+ (\S+)/x) { 
     $current = $messages{ $msg }; 
    } 
    elsif ( ref($current) 
      and my ($before, $member, $after) 
        = m/^(\s* Member \s+ (\w+) \s+ \w+) \s+ (.*) /x 
     ) { 
     if (my $vals = $current->{ $member }) { 
      $_ = "$before CONSTRAINT @$vals $after"; 
     } 
    } 
    say; 
} 

__DATA__ 
MESSAGE: FOO_TELEM 
latitude [-90,90] 
longitude [-180,180] 
MESSAGE: FOO_FREQUENCY 
airPressure [0,50] 
engineSpeed [0,65500] 
--- 
MessageTable 
    Message FOO_TELEM 
    Member latitude DOUBLE End-Member 
    Member longitude DOUBLE End-Member 
    End-Message 
    Message FOO_FREQUENCY 
    Member airPressure ULONG End-Member 
    Member engineSpeed ULONG End-Member 
    End-Message 
End-MessageTable 
+0

환상적. 귀하의 솔루션은 즉시 사용할 수 있습니다. 감사. – Karimi

1

먼저, 다음과 같은 데이터 구조로 데이터를로드하는 파서를 작성 :

다음
my %data = (
    FOO_TELEM => { 
     latitude => [ -90, 90 ], 
     longitude => [ -180, 180 ], 
    }, 
    FOO_FREQUENCY => { 
     latitude => [ 0, 50 ], 
     longitude => [ 0, 65500 ], 
    }, 
); 

, 데이터 정의 포맷에 대한 파서를 작성. 유일한 추가는 End-Member을 찾으면 $data{$message_name}{$member_name}을 찾도록하는 것입니다.

0

일부 표준 형식으로되어 있습니까? 도움이 될 것입니다. 파일이 특정 표준 형식이 아닌 경우에 당신은 그 표준 형식으로 얻을 수

<messageTable> 
    <message name="FOO_TELEM"> 
     <member name="latitude" type="DOUBLE"/> 
     <member name="longitude" type="DOUBLE"/> 
    </message> 
    <message name="FOO_FREQUENCY"> 
     <member name="airPressure" type="ULONG"/> 
     <member name="engineSpeed" type="ULONG"/> 
    </message> 
</messageTable> 

을 : 당신의 Config.txt 파일이 XML 형식 인 경우 예를 들어,이 같을까요? XML 일 필요는 없습니다. YAML도 좋습니다.

필자가 요구하는 이유는 Perl이 모든 것을 쉽게 조작 할 수 있도록 이러한 표준 형식을 빠르게 구문 분석하기위한 모듈을 골고루 가지고 있다는 것입니다. 그렇지 않으면 수동으로 데이터를 구문 분석하여 정보를 추출해야합니다.

가장 쉬운 방법은 테이블을 구문 분석하고 Perl에서 복잡한 데이터 구조를 만들어 ICD.txt 파일 정보를 저장하는 것입니다. Perl에는 세 가지 표준 데이터 유형, 즉 Scalars ($foo과 같은 변수), 배열 (@foo과 같은 변수) 및 해시 (%hash과 같은 변수)가 있습니다. 이러한 각 데이터 유형은 개별 값을 처리합니다. 스칼라에는 하나의 개별 값만 포함될 수 있으며 배열과 해시는 이러한 값 목록을 처리합니다.

더 복잡한 구조를 다루려면 Perl References을 사용해야합니다. 참조를 사용하면 해시 또는 배열 배열, 배열 해시 또는 해시 배열 등의 해시를 가질 수 있습니다.예를 들어

:

이이 모양에 ICD 데이터를 얻을 것이다
use strict; 
use warnings; 
use feature qw(say); 
use autodie; 
use Data::Dumper; 

open my $icd_fh, "<", "icd.txt"; 

my %icd_data; 
my $message; 
while (my $line = <$icd_fh>) { 
    if ($line =~ /^MESSAGE: (.*)/) { 
     $message = $1; 
    } 
    else { 
     $line =~ /(.*) \[(.*),(.*)\]/; 
     my $message_type = $1; 
     my $lower_limit = $2; 
     my $upper_limit = $3; 
     if (not exists $icd_data{$message}) { 
      $icd_data{$message} = {}; 
     } 
     $icd_data{$message}->{$message_type} = {}; 
     $icd_data{$message}->{$message_type}->{LOWER} = $lower_limit; 
     $icd_data{$message}->{$message_type}->{UPPER} = $upper_limit; 
    } 
} 
say Dumper \%icd_data; 

:

$VAR1 = { 
      'FOO_TELEM' => { 
       'longitude' => { 
        'LOWER' => '-180', 
        'UPPER' => '180' 
       }, 
       'latitude' => { 
         'LOWER' => '-90', 
         'UPPER' => '90' 
       } 
      }, 
      'FOO_FREQUENCY' => { 
       'airPressure' => { 
        'LOWER' => '0', 
        'UPPER' => '50' 
       }, 
       'engineSpeed' => { 
        'LOWER' => '0', 
        'UPPER' => '65500' 
       } 
      } 
    }; 

이 거기에서, 당신은 당신의 Config.txt 파일의 라인을 구문 분석 할 수 있어야하고이를 수정해야합니다 필요한 데이터로

관련 문제