2010-02-01 3 views
6

필자는 공간 분리 된 16 진수 형식의 16 진수 형식의 원시 패킷을 네트워크를 통해 수신하는 Java 프로그램을 가지고 있습니다. 그 코드를 변경하고 싶지 않기 때문에 이론적으로 단순히 unpack this를 STDIN에서 인식 가능한 변수로 변환 할 수있는 Perl 스크립트로 결과를 파이프합니다. 내 펄 파일의 라인 입력의 샘플은 다음과 같습니다Perl에서 압축을 푼 공간 분리 된 STDIN 16 진수 문자열을 어떻게 파싱 할 수 있습니까?

 
FF FF 09 7D 10 01 07 01 00 02 00 1D 00 00 00 00 00 06 00 07 00 
|--garbage-----|c--|c--|int---|int---|int---|int---|int---|int---|int---| 

내가 처음에 깔끔하게 각 입력을 구분 unpack을 사용하고 싶었

(C는 문자/바이트에 대한 16 비트 정수 변수가 int) 내가 필요로하는 변수에 줄을 써라. 그러나 문자열의 공백 구분으로 인해 나는 그것을 처리하는 방법을 잘 모르겠다. (나는 'A'를 템플릿으로 사용할 수 있지만 split을 사용해야 할 수도있다.)

우아한 방법이 있는가? unpack()을 사용하고 계십니까? 나는 Perl 마스터가 아니지만 다른 방법은 앞서 제안한대로 split을 사용하고 수동으로 각 16 진수를 바이트로 변환 한 다음 비트 조작과 마스크를 사용하여 원하는 결과를 얻는 것입니다. 다른 제안 (unpack이 그 날을 저장하지 않는다면)?

답변

8

, 그것은 자신의 값에 따라 바이트 (C*)에 포장하여 시작합니다

#! /usr/bin/perl 

use warnings; 
use strict; 

# for demo only 
*ARGV = *DATA; 

while (<>) { 
    my @fields = unpack "x5C2n7", 
       pack "C*", 
       map hex, split; 

    print "[", join("][" => @fields), "]\n"; 
} 

__DATA__ 
FF FF 09 7D 10 01 07 01 00 02 00 1D 00 00 00 00 00 06 00 07 00 

사용합니다.

:

  • x5 다섯 개 바이트
  • C2 디코딩이 개 unsigned char
  • n7가 디코딩 일곱 16 비트 빅 엔디안 부호없는 정수

출력을 건너 뛰고 다음 unpack 템플릿은 다음과 같은 부분이 있습니다

$ ./dump-packets 
[1][7][256][512][7424][0][0][1536][1792]
+0

'map {hex} split'을 쓰면 더 예쁘게 보이게 할 수 있습니다 :) – friedo

+2

아니면'Map hex, split' - 거의 하스켈! –

+0

실제로 바이트가 리틀 엔디안인지 확인했습니다. wierd, 그들이 네트워크를 통해 전송되면서, 나는 그것이 네트워크 순서에 있어야한다고 생각했을 것이다. 오 그럼, 유일한 변화는 "x5C2v7"의 압축을 풀 때 "x5C2n7"의 압축을 풀어야합니다. 그리고 답장을 보내 주셔서 감사합니다 ...이 포럼은 최고입니다 – intiha

3

압축을 푼 데이터를 압축 해제하려면 먼저 압축해야합니다. 그리고 그 전에 공간을 제거해야합니다. 즉

, 이들의 int는 빅 엔디안 순서대로 가정

$line =~ tr/ //d;   # remove spaces 
$line = pack 'H*', $line; # convert hex to binary 
# Now you can use unpack. 
+0

사실 저는 이 솔루션은 위의 제안 된 압축 풀기와 결합하여 깨끗하게 보였습니다 (코드가 무엇을하는지 이해함). 자바 코드가 에러 문자열을 내면 $ 라인을 파싱 할 수도있다. – intiha

관련 문제