2015-10-05 42 views
3

問題:爲什麼如下所述是代碼切斷了一些字段的最後一個字符?問題與反斜坡鼠疫和re.split

我有一個字符串,我需要解析,拆分,然後作爲鍵/值導入字典。我的問題是一個字段可能包含多個嵌入逗號分隔的子字段,但在這些情況下,逗號前有三個反斜槓。我有代碼99%的工作,但由於某種原因使用下面的代碼(我認爲應該工作)導致所有其他領域的最後一個字符被剝奪。我認爲我理解Python Regex中的「反斜槓瘟疫」,我嘗試了幾種方法,但是找不到既不會分裂「ConfigChangeData」也不會放棄其他字段的最後一個字符的方法。

首先,這裏是我開始的字符串(在一個變量稱爲數據):

2015-10-05 18:08:47,186 root   INFO  <181>Oct 5 17:09:10 someservername Administrative_and_Operational_Audit 0000419602 1 0 2015-10-05 17:09:10.841 -05:00 0000006065 52001 NOTICE Configuration-Changes: Changed configuration, Version=someversion.x86_64, ConfigVersionId=150, AdminInterface=GUI, AdminIPAddress=192.168.1.77, AdminSession=46CE916D0502A641592B105FF7CB3B70, AdminName=admin, ConfigChangeData='RADIUS:Shared Secret'='********'\\\,'TACACS+:Shared Secret'='********'\\\,'IP Address'='127.0.0.91/32', ObjectType=Network Device, ObjectName=testclient, ObjectId=4072, inLocalMode=false, 

這裏是我的代碼:

##split the syslog data into CSV's in a list 
#Here be dragons: One field, "ConfigChangeData" can have multiple embedded 
#subfields. This is indicated by three trailing backslashes 
#The following line needs to split on commas NOT proceeded by a backslash 
csvlist=re.split("[^\\\\],", data) 
AVPdict=dict() 
##Create an Attribute/value pair by analysing the CSV values 
##If the CSV value represents a AVP pair (detected by presense of an = sign) 
##add it to the AVP dict 
for csv in csvlist: 
    logger.debug("csv: %s" %(csv)) 
    if re.search("=", csv): 
     csv=csv.strip() # clear out some embedded whitespace 
     attribute,value=csv.split("=", 1) 
     AVPdict[attribute]=value 

下面是從日誌輸出:

2015-10-05 18:08:47,189 root   DEBUG csv: Version=someversion.x86_6 
2015-10-05 18:08:47,190 root   DEBUG csv: ConfigVersionId=15 
2015-10-05 18:08:47,190 root   DEBUG csv: AdminInterface=GU 
2015-10-05 18:08:47,190 root   DEBUG csv: AdminIPAddress=192.168.7 
2015-10-05 18:08:47,191 root   DEBUG csv: AdminSession=46CE916D0502A641592B105FF7CB3B7 
2015-10-05 18:08:47,191 root   DEBUG csv: AdminName=admi 
2015-10-05 18:08:47,191 root   DEBUG csv: ConfigChangeData='RADIUS:Shared Secret'='********'\\\,'TACACS+:Shared Secret'='********'\\\,'IP Address'='127.0.0.91/32 
2015-10-05 18:08:47,192 root   DEBUG csv: ObjectType=Network Devic 
2015-10-05 18:08:47,192 root   DEBUG csv: ObjectName=testclien 
2015-10-05 18:08:47,192 root   DEBUG csv: ObjectId=407 
2015-10-05 18:08:47,193 root   DEBUG csv: inLocalMode=fals 
2015-10-05 18:08:47,193 root   DEBUG csv: 
+0

'「\\\\」包括'是與'r'\''相同。我不確定你的3個反斜槓在哪裏。 –

+0

這三個反斜槓是在匹配的字符串中:ConfigChangeData ='RADIUS:Shared Secret'='********'\\\,'TACACS +:Shared Secret'='******* *'\\\,'IP Address'='127.0.0.91/32': – wvunathans

回答

2

你的正則表達式模式正在消耗逗號之前的最後一個字符,因爲這個字符是你模式的一部分,重新分裂。它是由醜陋的[^\\\\]位模式匹配的字符。

我認爲你想要一個負面後顧之憂。這可以讓你檢查前面的字母是不是反斜槓,而不是實際在匹配中包含該字符。

csvlist=re.split(r"(?<!\\),", data) 

請注意,我使用的是原始字符串,所以你只需要兩個反斜槓,而不是你最初使用四個。

+0

D'oh。我非常關注「當反斜槓匹配」條件時,我忘記了「當反斜槓不匹配」時。我嘗試了原始字符串,但無法啓動它,爲什麼現在很明顯。就像老引用一樣:有些人遇到問題時,會想:「我知道,我會用正則表達式。」現在他們有兩個問題。 – wvunathans

+0

在「兩個問題」方面,如果您傳遞'escapechar'關鍵字變量,則Python的'csv'模塊可以處理逗號分隔的字符串,因此如果您有多行數據(而不僅僅是一行),則可能值得嘗試而不是're'。 – Blckknght

+0

@Blckknght我打算建議使用[**'csv' **](https://docs.python.org/2/library/csv.html),但[**'escapechar' **] (https://docs.python.org/2/library/csv.html#csv.Dialect.escapechar)只是一個字符。 –

0

您需要爲您re.split模式的回顧後,這樣的逗號之前的字符不是定界符(即拆分字符)

re.split(r"(?<=[^\\]),",data)