2010-07-10 41 views
-1

我需要下面的Perl函數轉換爲PHP:轉換一個Perl代碼PHP

pack("SSA12AC4L", 
    $id, 
    $loc, 
    $name, 
    'ar', 
    split(/\./, $get->getIP), 
    time+(60*60); 

我用下面的代碼(測試)在PHP中:

echo pack("SSA12AC4L", 
    '25', 
    '00001', 
    '2u7wx6fd94fd', 
    'f', 
    preg_split('/\./','10.2.1.1', -1, PREG_SPLIT_NO_EMPTY), 
    time()+(60*60)); 

但我出現以下錯誤: 警告:pack()[function.pack]:類型C:第8行D:\ wamp \ www \ test.php中的參數太少

有什麼建議嗎?非常感謝。

回答

0

的問題是,代碼是給予pack()(我指的是最後一個參數)一個字符,一個數組和一個整數。由於代碼C需要4個字符,這是錯誤的原因。

代碼應該是這樣的

$split = preg_split('/\./','10.2.1.1', -1, PREG_SPLIT_NO_EMPTY); 
echo pack("SSA12AC4L", 
    '25', 
    '00001', 
    '2u7wx6fd94fd', 
    'f', 
    $split[0], 
    $split[1], 
    $split[2], 
    $split[3], 
    time()+60*60 
); 

然後,沒有理由在這種情況下使用preg_split(),當explode()可以用來代替。正則表達式只能在嚴格需要時使用,因爲與其他字符串函數相比,正則表達式函數較慢。

+0

謝謝,它工作正常:) – Slim 2010-07-10 20:27:13

6

來自pack()的PHP文檔。

Pack given arguments into binary string according to format.

The idea for this function was taken from Perl and all formatting codes work the same as in Perl. However, there are some formatting codes that are missing such as Perl's "u" format code.

當然,它應該就這樣工作?您可能需要重新命名一些變量

+0

+1的RTFM鍛鍊:) – 2010-07-10 01:06:09

+1

@George:不妨嘗試幫助反正,雖然。 – icktoofay 2010-07-10 01:07:55

+2

@icktoofay「給一個人一條魚,喂他一天......」 – 2010-07-10 01:15:52

-1

我沒有看過這麼長時間,但我注意到的第一件事是您有一個開放paren和三個關閉。 「時間」應該是$時間嗎?

+0

http:/ /perldoc.perl.org/functions/time.html – daxim 2010-07-10 08:26:03

+0

時間不是變量 – Slim 2010-07-10 14:25:11

0

我認爲問題在於preg_split返回一個數組。所以數組插入爲第一個字符,時間爲第二個,剩下兩個字符。

我不知道如何解決這個問題,但創建一個臨時數組:

$ip = explode('.','10.2.1.1'); 

然後:

echo pack("SSA12AC4L", 
'25', 
'00001', 
'2u7wx6fd94fd', 
'f', 
$ip[0], 
$ip[1], 
$ip[2] 
$ip[3], 
time()+(60*60)); 
+0

感謝您的建議。 – Slim 2010-07-10 20:27:53

0

問題是,PHP preg_split正在將其轉換爲數組。你需要一個無符號的字符,所以使用

$x = intval(implode("", preg_split('/\./','10.2.1.1', -1, PREG_SPLIT_NO_EMPTY))); 
echo pack('SSA12ACL', 
    '25', 
    '00001', 
    '2u7wx6fd94fd', 
    'f', 
    $x, 
    time()+(60*60)); 

讓我們知道它是怎麼回事。

+0

和其他海報說的,如果您不期望IP以外的其他任何內容,則可以使用爆炸代替preg_split。 – pinaki 2010-07-10 19:38:39

1

有時候,錯誤語句意味着值得回顧。參數太少可能意味着需要檢查PHP包語句中使用的每個輸入與預期格式一致。

例如,您是否考慮過perl pack語句中使用的'ar'字段?因此,您可能會在一個字段中關閉打包的數據。

0

我的第一個建議是,你仔細閱讀的文檔。這個問題與perl很少有關,並且與理解函數的期望有很大關係。我的第二個建議是,當你複製一些代碼時,養成一點緊張的習慣。緊張得足以讓代碼,文檔等得到額外的關注。至少,當客戶/老闆/誰問你什麼是複製的代碼時,你應該有一個很好的答案。

pack()的第一個參數是格式字符串。這決定了它在創建輸出時如何格式化參數。

documentation的包():

The format string consists of format codes followed by an optional repeater argument. The repeater argument can be either an integer value or * for repeating to the end of the input data. For a, A, h, H the repeat count specifies how many characters of one data argument are taken, for @ it is the absolute position where to put the next data, for everything else the repeat count specifies how many data arguments are consumed and packed into the resulting binary string.

那麼,問題是,你的格式字符串不適合你傳遞給包()的參數。現在,請記住,我必須根據您的需要猜測適當的格式字符串。您必須閱讀文檔並確定正確的格式字符串。

以下作品就好:

echo pack("SSA12ACL", 
'25', 
'00001', 
'2u7wx6fd94fd', 
'f', 
preg_split('/\./','10.2.1.1', -1, PREG_SPLIT_NO_EMPTY), 
'1278761963'); 

函數使preg_split()返回一個單個陣列。但是,原始格式字符串中的'C4'預計需要4個參數。根據我的計數,原始格式字符串隱含9個參數,而不是6.

+0

這不會「工作得很好」,它將IP地址應該是一個完整的垃圾字符。如何用'a4'打包'inet_pton($ addr)'或用'N'打包'ip2long($ addr)'? – hobbs 2010-07-10 23:41:48

+0

@hobbs正如我所指出的,我不知道他希望格式化輸出。另請注意,輸出是** BINARY **字符串。 「在這種情況下,術語二進制字符串和字節字符串用於建議存儲的數據不(必然)表示文本的字符串。」 http://en.wikipedia.org/wiki/String_%28computer_science%29 – 2010-07-10 23:45:22

+0

我知道你必須猜測。但是猜測原始格式(來自工作代碼)是錯誤的,並且它以某種方式有意義地用單個字節表示IP地址可能不是一個很好的猜測;猜測原始格式是正確的,並且它意味着以規範的方式表示一個IP地址(網絡順序是4個字節)是明智的。困難似乎來自於perl在參數列表中展平列表並且PHP不支持。我不知道你的「** BINARY **字符串」咆哮應該告訴我們,我們不知道。 – hobbs 2010-07-10 23:55:40

1

看起來像在Perl中,如果將函數調用放在參數列表的中間,被調用的函數返回一個列表,該列表中的項目被「拼合」以產生多個參數到外部函數; PHP不會做任何類似的事情,這就是你的論點不匹配的地方(分割應該產生四個參數來打包,但PHP只能看到一個 - 值爲array)。

幸運的是,解決這個問題的方法非常簡單,因爲內建函數可以在沒有任何體操的情況下複製所需的內容。嘗試:

echo pack("SSA12ANL", 
'25', 
'00001', 
'2u7wx6fd94fd', 
'f', 
ip2long('10.2.1.1'), 
'1278761963'); 

,或者以某種方式失敗:

echo pack("SSA12Aa4L", 
'25', 
'00001', 
'2u7wx6fd94fd', 
'f', 
inet_pton('10.2.1.1'), 
'1278761963');