2012-03-07 177 views
1

我有一個字符串爆炸的字符串:有沒有辦法用一個「模式」

mystring = "Foo: Bar (Titi) Foo-age: 50 Airplanes: 12:1 12:3 12:4 12:5 [...] Next Hop: LAX Origine ID: 49 Hop List 2 4 9 0 3 [...]" 

有沒有辦法使用的模式,像拆分此字符串:

pattern = {"Foo", "Foo-age", "Airplanes", "Next Hop", "Origine ID", "Hop List"} 

和那麼

mylist = somefunction(mystring , pattern) 
print mylist 
--> {"Foo":"Bar (Titi)","Foo-age" : 50, "Airplanes": ["12:1","12:3",...], ...} 

這是可能的蟒蛇?

[編輯]

某些樣本數據 - 5-COL csv文件瓦特/定界符 「」

col-1,col-2,Path: 9876 (IGP) Local-Pref: 310000 MED: 0 Communities: 1234:6 1234:95 1234:101 1234:202 1234:500 1234:903 1234:3369 1234:8000 1234:8002 1234:16925 9876:19827 Next Hop: x.x.127.151 Originator ID: x.x.155.144 Cluster List: 0.0.29.99 0.0.29.97 0.0.26.245 0.0.2.179 ,col-4,col-5 

col-1,col-2,Path: 9876 (IGP) Local-Pref: 310000 MED: 0 Communities: 1234:3 1234:95 1234:101 1234:202 1234:13705 9876:19941 Next Hop: x.x.127.61 Originator ID: x.x.137.37 Cluster List: 0.0.29.99 0.0.29.97 0.0.1.195 ,col-4,col-5 

col-1,col-2,Path: 9876 (IGP) Local-Pref: 310000 MED: 0 Communities: 1234:2 1234:95 1234:101 Next Hop: x.x.127.149 Originator ID: x.x.137.29 Cluster List: 0.0.29.99 0.0.29.98 0.0.2.240 ,col-4,col-5 

col-1,col-2,Path: 9876 (IGP) Local-Pref: 310000 MED: 0 Communities: 1234:6 1234:95 1234:101 1234:202 1234:500 1234:903 1234:3369 1234:8000 1234:8002 1234:16924 9876:19827 Next Hop: x.x.127.151 Originator ID: x.x.155.144 Cluster List: 0.0.29.99 0.0.29.97 0.0.26.245 0.0.2.179 ,col-4,col-5 
+0

我可以使用正則表達式,但我的字符串對每一行不完全一樣的格式(它來自一個「」「csv」「」文件) – Franquis 2012-03-07 09:12:24

+1

如果正則表達式不會這樣做,那麼它是可疑的,你可以在一行。也許你應該更清楚地解釋這個問題,因爲正則表達式可以在需要時忽略換行符之類的東西。顯示一些給您帶來麻煩的示例數據。 – SpliFF 2012-03-07 09:17:36

+1

我相信基於csv文件的解決方案可能會更容易。你能否給這個問題增加一個例子? – jcollado 2012-03-07 09:18:06

回答

2

我認爲這可以分兩步完成。首先,您尋找類似字段名稱(Foo-Bar:)的內容,並在每次比賽前插入一個「特殊」標記字符(例如@)。其次,您要查找的模式marker field-name : data和填充數據字典:

text = """ 
col-1,col-2,Path: 9876 (IGP) Local-Pref: 310000 MED: 0 Communities: 1234:6 1234:95 1234:101 1234:202 1234:500 1234:903 1234:3369 1234:8000 1234:8002 1234:16925 9876:19827 Next Hop: x.x.127.151 Originator ID: x.x.155.144 Cluster List: 0.0.29.99 0.0.29.97 0.0.26.245 0.0.2.179 ,col-4,col-5 
""" 

import re 

text = re.sub(r'([A-Z][A-Za-z -]+:)', r'@\1', text) 
data = {} 
for m in re.finditer(r'@(.+?):([^,@]+)', text): 
    data[m.group(1)] = m.group(2).strip() 

import pprint 
pprint.pprint(data) 

結果:

{'Cluster List': '0.0.29.99 0.0.29.97 0.0.26.245 0.0.2.179', 
    'Communities': '1234:6 1234:95 1234:101 1234:202 1234:500 1234:903 1234:3369 1234:8000 1234:8002 1234:16925 9876:19827', 
    'Local-Pref': '310000', 
    'MED': '0', 
    'Next Hop': 'x.x.127.151', 
    'Originator ID': 'x.x.155.144', 
    'Path': '9876 (IGP)'} 
+0

非常有趣的方法!它的作品完美 – Franquis 2012-03-07 10:39:51

1

這一個可能有點棘手。

請註明更多,但現在這個解決方案應該要麼足矣或讓你更接近你的願望:

mystring = "Foo: Bar (Titi) Foo-age: 50 Airplanes: 12:1 12:3 12:4 12:5 Next Hop: LAX Origine ID: 49 Hop List: 2 4 9 0 3" 
pattern = {"Foo", "Foo-age", "Airplanes", "Next Hop", "Origine ID", "Hop List"} 
to_list = {'Airplanes', 'Hop List'} 
def obtain_data(mystring, pattern, to_list):  
    result = {} 
    prev_pattern = None 
    prev_pos = 0 
    ordered_pattern = sorted(list(pattern), key=lambda x: mystring.find(x + ':')) 
    for p in ordered_pattern: 
     npos = mystring.find(p +':', prev_pos) 
     if prev_pattern is not None: 
      to_add = mystring[prev_pos+len(prev_pattern)+1 : npos].strip() 
      if prev_pattern in to_list: 
       to_add = to_add.split() 
      result[prev_pattern] = to_add 
     prev_pos = npos 
     prev_pattern = p 
    to_add = mystring[prev_pos+len(prev_pattern)+1 : len(mystring)].strip() 
    if prev_pattern in to_list: 
     to_add = to_add.split() 
    result[prev_pattern] = to_add 
    return result 

obtain_data(mystring, pattern, to_list) 

這將返回:

{'Foo-age': '50', 'Hop List': ['2', '4', '9', '0', '3'], 'Airplanes': ['12:1', '12:3', '12:4', '12:5'], 'Next Hop': 'LAX', 'Foo': 'Bar (Titi)', 'Origine ID': '49'} 

我第一次分揀模式成根據它們在字符串上出現的位置列出一個列表。

我在考慮在模式之後總是有':'。如果情況並非如此,那麼可能會證明這樣做太難了(考慮到可能有一種模式是另一種模式的前綴,例如您展示的Foo和Foo-age)。另一件事是:如果你想讓其中一個值成爲一個列表,你必須指定哪些模式將它們的值轉換爲列表作爲第三個參數。如果你不認爲你會一直這樣做,那麼你可以提供一個空集或者跳過這個,但是我只遵循你的例子所展現的。

最後編輯:在這種情況下,你將有可能無法對碼出現的模式,你可以用

ordered_pattern = filter(lambda x: mystring.find(x) != -1, ordered_pattern) 

權前的篩選排序列表的結果爲循環

希望這可以爲你服務:)

相關問題