反斜杠瘟疫和重新分裂的问题

Posted

技术标签:

【中文标题】反斜杠瘟疫和重新分裂的问题【英文标题】:issue with Backslash plague and re.split 【发布时间】:2016-01-02 17:31:55 【问题描述】:

问题:为什么如下所述的代码会切断某些字段的最后一个字符?

我有一个需要解析、拆分然后作为键/值导入字典的字符串。我遇到的问题是一个字段可能包含多个嵌入的逗号分隔子字段,但在这些情况下,逗号前面有三个反斜杠。我有 99% 的代码工作,但由于某种原因,使用以下代码(我认为应该工作)导致所有其他字段的最后一个字符被剥离。我想我理解 Python Regex 中的“反斜杠瘟疫”,我尝试了几种方法,但找不到既不拆分“ConfigChangeData”也不删除其他字段的最后一个字符的方法。

首先,这是我开始的字符串(在一个名为 data 的变量中):

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:

【问题讨论】:

'\\\\'r'\\' 相同。我不确定你的 3 个反斜杠在哪里。 三个反斜杠在匹配的字符串中:ConfigChangeData='RADIUS:Shared Secret'='********'\\\,'TACACS+:Shared Secret'=' ********'\\\,'IP地址'='127.0.0.91/32': 【参考方案1】:

您的正则表达式模式正在使用逗号之前的最后一个字符,因为该字符是您要拆分的模式的一部分。它是与模式中丑陋的[^\\\\] 位匹配的字符。

我认为你想要一个消极的后视。这将让您检查前面的字母是否不是反斜杠,而实际上并未在匹配中包含该字符。

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

请注意,我使用的是原始字符串,因此您只需要两个反斜杠,而不是您最初使用的四个。

【讨论】:

哦。我非常专注于“反斜杠匹配时”条件,我忘记了“反斜杠不匹配时”。我尝试了原始字符串但无法让它工作,为什么现在很明显。就像那句老话:有些人在遇到问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题。 在“两个问题”前面,如果您传递 escapechar 关键字变量,Python 的 csv 模块可以处理逗号分隔的字符串,所以如果您有多行数据(而不仅仅是一个) 它可能值得尝试而不是re @Blckknght 我也打算建议使用csv,但escapechar 只是一个字符。 @PeterWood:这是一个很好的观点,但目前我们忽略了re 代码中的两个额外的反斜杠,所以在csv 模块代码中也忽略它们可能不会有什么坏处.使用re,如果您愿意,可以检查三个反斜杠,而不仅仅是一个。【参考方案2】:

您需要查看 re.split 模式,以便逗号之前的字符不包含在分隔符中(即拆分字符)

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

【讨论】:

以上是关于反斜杠瘟疫和重新分裂的问题的主要内容,如果未能解决你的问题,请参考以下文章

斜杠/,反斜杠,斜杠/,点斜杠./,点点斜杠../

MySQL中如何插入反斜杠,反斜杠被吃掉,反斜杠转义(转)

python urlencode() 反斜杠处理问题

斜杠反斜杠以及换行符

python中将反斜杠'\'变为正斜杠'/'

zeroclipboard复制反斜杠时不正确的解决办法