如何从未成形的字符串中分离字符串

时间:2013-06-05 18:16:46

标签: python

我有这种格式的字符串

 2013-06-05T11:01:02.955 LASTNAME=Jone FIRSTNAME=Jason PERSONNELID=salalm QID=231412 READER_NAME="CAZ.1 LOBBY LEFT TURNSTYLE OUT" ACCESS_TYPE="Access Granted" EVENT_TIME_UTC=1370480141.000 REGION=UTAH

其中一些看起来像这样

 2013-06-05T11:15:48.670 LASTNAME=Ga FIRSTNAME="Je " PERSONNELID=jega QID=Q10138202 READER_NAME="CAZ.1 ELEVATOR LOBBY DBL GLASS" ACCESS_TYPE="Access Granted" EVENT_TIME_UTC=1370481333.000 REGION=UTAH

我想提取PERSONNELID,REGION,ACCESS_TYPE,EVENT_TIME_UTC

的值

我打算使用split(“”),但READER_NAME和ACCESS_TYPE值有一堆空格 我可以转换为JSON并按键搜索

提取这些字符串的方法是什么。

提前谢谢

3 个答案:

答案 0 :(得分:11)

我过去认为有用的一个黑客就是使用shlex.split

>>> s = '2013-06-05T11:01:02.955 LASTNAME=Jone FIRSTNAME=Jason PERSONNELID=salalm QID=231412 READER_NAME="CAZ.1 LOBBY LEFT TURNSTYLE OUT" ACCESS_TYPE="Access Granted" EVENT_TIME_UTC=1370480141.000 REGION=UTAH'
>>> split = shlex.split(s)
>>> split
['2013-06-05T11:01:02.955', 'LASTNAME=Jone', 'FIRSTNAME=Jason', 
'PERSONNELID=salalm', 'QID=231412', 'READER_NAME=CAZ.1 LOBBY LEFT TURNSTYLE OUT',
'ACCESS_TYPE=Access Granted', 'EVENT_TIME_UTC=1370480141.000', 'REGION=UTAH']

然后我们可以把它变成字典:

>>> parsed = dict(k.split("=", 1) for k in split if '=' in k)
>>> parsed
{'EVENT_TIME_UTC': '1370480141.000', 'FIRSTNAME': 'Jason', 
'LASTNAME': 'Jone', 'REGION': 'UTAH', 'ACCESS_TYPE': 'Access Granted', 
'PERSONNELID': 'salalm', 'QID': '231412', 
'READER_NAME': 'CAZ.1 LOBBY LEFT TURNSTYLE OUT'}

正如@abarnert所指出的,如果你愿意,你可以保留更多信息:

>>> dict(k.partition('=')[::2] for k in split)
{'2013-06-05T11:01:02.955': '', 'EVENT_TIME_UTC': '1370480141.000', 'FIRSTNAME': 'Jason', 'LASTNAME': 'Jone', 'REGION': 'UTAH', 'ACCESS_TYPE': 'Access Granted', 'PERSONNELID': 'salalm', 'QID': '231412', 'READER_NAME': 'CAZ.1 LOBBY LEFT TURNSTYLE OUT'}

等等。正如他所说的那样,关键点在于,您显示的语法看起来很像最小的shell语法。 OTOH,如果违反了你在其他地方展示过的模式,你可能会想回到编写自定义解析器。 shlex方法在适用时很方便,但不如您想要的那么强大。

答案 1 :(得分:3)

让我们分析一下问题:您想要匹配四个标识符中的一个,然后是=符号,然后是带引号的字符串或一系列非空白字符。

这对于正则表达来说是完美的工作:

>>> s= ' 2013-06-05T11:01:02.955 LASTNAME=Jone FIRSTNAME=Jason PERSONNELID=salal
m QID=231412 READER_NAME="CAZ.1 LOBBY LEFT TURNSTYLE OUT" ACCESS_TYPE="Access Gr
anted" EVENT_TIME_UTC=1370480141.000 REGION=UTAH'
>>> import re
>>> regex = re.compile(r"""\b(PERSONNELID|REGION|ACCESS_TYPE|EVENT_TIME_UTC)
...                        =
...                        ("[^"]*"|\S+)""", re.VERBOSE)
>>> result = regex.findall(s)
>>> result
[('PERSONNELID', 'salalm'), ('ACCESS_TYPE', '"Access Granted"'), 
 ('EVENT_TIME_UTC', '1370480141.000'), ('REGION', 'UTAH')]
>>> dict(result)
{'EVENT_TIME_UTC': '1370480141.000', 'PERSONNELID': 'salalm', 
 'ACCESS_TYPE': '"Access Granted"', 'REGION': 'UTAH'}

<强>解释

\b确保匹配从word boundary开始。

"[^"]*"匹配一个引号,后跟任意数量的非引号字符和另一个引号。

\S+匹配一个或多个非空白字符。

通过将正则表达式的“有趣”部分括在括号中,构建capturing groups,您可以分别获得匹配的每个部分的元组列表。

答案 2 :(得分:3)

寻找现有的解析器是个好主意。如果您可以找到已经描述过您数据的格式,或者您可以轻松地将数据转换为您的数据,那么您就赢了。

在这种情况下,转换为JSON似乎与首先解析一样多。

但您只是希望拆分为简单的valuename=value组件,其中value部分可以引用...这些规则与最小的shell语法相同。因此,shlex会为您完成:

>>> import shlex
>>> shlex.split('2013-06-05T11:01:02.955 LASTNAME=Jone FIRSTNAME=Jason PERSONNELID=salalm QID=231412 READER_NAME="CAZ.1 LOBBY LEFT TURNSTYLE OUT" ACCESS_TYPE="Access Granted" EVENT_TIME_UTC=1370480141.000 REGION=UTAH')
['2013-06-05T11:01:02.955',
 'LASTNAME=Jone',
 'FIRSTNAME=Jason',
 'PERSONNELID=salalm',
 'QID=231412',
 'READER_NAME=CAZ.1 LOBBY LEFT TURNSTYLE OUT',
 'ACCESS_TYPE=Access Granted',
 'EVENT_TIME_UTC=1370480141.000',
 'REGION=UTAH']

您仍然需要将每个name=value对分隔为名称和值组件,但这只是namevalue.split('=', 1)。但是,由于您有一些不是名称 - 值对的元素(2013-06-05T11:01:02.955),因此您需要单独执行此操作。

当然,您始终可以选择将它们视为具有空值的名称 - 值对:

>>> dict(namevalue.partition('=')[::2] for namevalue in shlex.split(s))
{'2013-06-05T11:01:02.955': '',
 'ACCESS_TYPE': 'Access Granted',
 'EVENT_TIME_UTC': '1370480141.000',
 'FIRSTNAME': 'Jason',
 'LASTNAME': 'Jone',
 'PERSONNELID': 'salalm',
 'QID': '231412',
 'READER_NAME': 'CAZ.1 LOBBY LEFT TURNSTYLE OUT',
 'REGION': 'UTAH'}