2010-02-01 22 views
6

我有一個Java程序,以空格分隔的十六進制格式吐出,通過網絡接收到16個字節的原始數據包。由於我不想更改該代碼,因此我將結果傳遞給一個Perl腳本,理論上,它可以簡單地將STDIN中的unpack轉換爲可識別的變量。以下是線路輸入到我的Perl文件的示例:如何解析在Perl中解壓的空格分隔的STDIN十六進制字符串?

 
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---| 

(c是用於字符/字節,對於16位整數變量int)

我最初想使用unpack每個輸入乾淨地分離行我需要的變量。但是,由於字符串中的空格分隔,我不知道如何處理它(我可以使用'A'作爲模板,但接下來我不妨使用split!)使用unpack()?我不是Perl的主人,但另一種方式是,正如我之前建議的那樣,使用split,然後手動將每個十六進制轉換爲一個字節,然後使用位操作和掩碼來獲得我想要的。任何其他建議(如果unpack不保存一天)?

回答

8
假設

那些整數是大端順序,使用

#! /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 

它通過在根據它們的值的字節(C*)包裝開始關閉。該unpack模板具有以下幾個部分:

  • x5跳過五個字節
  • C2解碼2個unsigned char
  • n7解碼7個16位大端無符號整數

輸出:

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

你可以通過說'map {hex} split'使它看起來更漂亮:) :) – friedo 2010-02-01 22:50:50

+2

甚至只是'map hex,split' - 幾乎是Haskell! – 2010-02-01 22:55:39

+0

實際上,我確認這些字節是在little endian中。因爲它們是通過網絡發送的,所以我會認爲應該是網絡順序。哦,唯一的變化就是需要解壓「x5C2n7」來解壓「x5C2v7」,對吧?並感謝您的答覆...這個論壇是真棒 – intiha 2010-02-02 01:26:39

3

如果你想使用解壓後的數據解包,你需要先打包。在你做這些之前,你需要刪除空格。

換句話說,

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

我其實是你因爲它看起來更清潔(我明白代碼在做什麼)以及上面提到的拆箱。如果java代碼吐出一個錯誤字符串,我也可以解析$ line。 – intiha 2010-02-02 01:27:52

相關問題