2016-01-04 53 views
2

我對正則表達式很陌生,但決定使用它們來反序列化PHP數組。這裏有一些背景信息:Python:使用正則表達式反序列化PHP數組

我重寫了用PHP編寫的django中的公司基於數據庫的網站。與公司和行業有M2M關係。在以前的模型中,它是通過使用序列化的PHP數組解決的,所以我現在必須正確地同步所有內容。我的第一次嘗試是一些分裂和切割,這真的很難看,所以我決定跳入正則表達式。下面是我得到了什麼(它的工作完美的罰款)現在:

def unserialize_array(serialized_array): 
    import re 
    matched_sub = re.search('^a:\d+:\{i:\d+;s:\d+:"(.*?)";\}$', serialized_array).group(1) 
    industry_list = re.sub('";i:\d+;s:\d+:"', "? ", matched_sub).split("? ") 
    new_dict = dict(enumerate(industry_list)) 
    return new_dict 

我不過想知道如果我不能做到這一切與一個正則表達式,而不是兩個。

+0

[python中反序列化PHP數據]的可能的複製(http://stackoverflow.com/questions/5935501/unserialize-php-data-in-python) –

+0

否,決定不使用套餐的像phpserialize因爲它比我需要的還要多,並且會導致不必要的錯誤,例如我的數組數據的長度,因爲它包含德語元音變音。 –

+0

@FynnBecker:你能提供一些關於我提出的解決方案的反饋嗎?我的假設是正確的,或者你可以提供一些示例輸入? –

回答

0

更新:更新到正確處理也逃脫引號\"(實際寫入\\")和(轉義逃逸\\\"\\\\\\"後作爲一個轉義引號)任何轉義序列。


我想,如果我理解你輸入正確的結構,即你可以重寫你的方法是這樣的:

def unserialize_array(serialized_array): 
    import re 
    return dict(enumerate(re.findall(r'"((?:[^"\\]|\\.)*)"', serialized_array))) 

假定輸入(至於是不是你的問題明確指定) :

a:3:{i:1;s:9:"industry\\\\\\"A\\"";i:2;s:9:"\\"industry2\\"";i:3;s:9:"industry3"} 

輸出

{0: '產品生產技術\\\ 「A \」',1: '\ 「industry2 \」',2: 'industry3'}

(實際上:{0: 'industry1\\\\\\"A\\"', 1: '\\"industry2\\"', 2: 'industry3'}

它是如何作品

沒有必要匹配序列化數組的整個結構,因爲我們只關心字符串內容。正則表達式"((?:[^"\\]|\\.)*)"只是提取每個字符,直到遇到一個轉義「\」(在這種情況下接受轉義+另一個字符)或結束雙引號"

捕獲組確保在最終結果中刪除雙引號。

最後,re.findall方法在一次調用中返回由我們期望的結果組成的字符串列表。

這是一個特殊的re.findall覆蓋整個比賽,如果至少有一個捕獲組存在匹配(或由我們的情況下的捕獲組)。事實上,文檔聲明:

如果模式中存在一個或多個組,則返回一組組列表;如果模式有多個組,這將是一個元組列表。

+0

完美,這就是我一直在尋找的。不知道findall是否適合我的情況,以及如何使用捕獲組來刪除引號。還有一些混淆思想,我必須匹配完整的字符串才能工作。非常感謝您的回答,真的很有幫助。 –

0

建議使用帶回調的re.sub,它只會在遞歸中調用unserialize_array。

+0

不知道這一點,只是看起來它是如何工作的(python初學者),更確定漂亮,所以非常感謝。然而,我的問題仍然存在,在某種表達方式中是否可行? –