【问题标题】:parsing space delimited, named fields解析空格分隔的命名字段
【发布时间】:2014-03-24 13:20:18
【问题描述】:

我有一种特定格式的数据(从splunk> 导出),它是 CSV 和命名字段的混合体。我想了解在 Python 中是否可以通过模板(或简化的、普通人可以理解的正则表达式)解析此类数据

"Harry Potter", "book", "12 Mar 2014 note=""good"" language=""English"""
"Forrest Gump", "movie", "14 March 2015 note=""good"" language=""Aztec"""

如您所见,第一个字段以逗号分隔,然后是一个以日期开头的长字符串,然后是一些命名字段(notelanguage)。

我想仅从命名字段构建一个字典列表:

[
    {'note': 'good', 'language'='English'},
    {'note': 'good', 'language'='Aztec'}
]

解析 CSV 后,我得到了最后一个字段(例如第一行的 "12 Mar 2014 note=""good"" language=""English""")然后我被卡住了,我能想到的唯一解决方案是尝试在正则表达式中描述该行(这很可怕:)。即使我设法提取了元组,如何将它们翻译成字典?

【问题讨论】:

  • 如果最后一个字段不是特别复杂并且在您指定的格式中几乎是固定的,那么您可以继续使用正则表达式来获取数据。
  • 命名字段中的文本是否可以包含空格?例如。 note=""very good"".
  • @WarrenWeckesser:是的,对不起,我应该说清楚。

标签: python regex parsing csv dictionary


【解决方案1】:

csv 模块将为您处理外部 双引号,开箱即用。您的列有外引号(确保保留值中的分隔符、引号和换行符),并且值中的任何引号都加倍; csv.reader() 将删除外部引号并返回第三列的单引号字符串。

命名字段可以用正则表达式处理:

import csv
import re

keyvalue = re.compile(r'([^"= ]+)="([^"]+)"')


with open(filename, 'rb') as infh:
    reader = csv.reader(infh, skipinitialspace=True)
    namedfields = [dict(keyvalue.findall(row[2])) for row in reader]

skipinitialspace 选项删除分隔符后的所有空格;这是为了确保正确删除引用的列值之前的空格,从而确保处理引用。

这里的re.findall() 方法返回一个(key, value) 元组列表,dict() 类型会将它们直接转换成字典。

演示:

>>> import csv
>>> import re
>>> keyvalue = re.compile(r'([^"= ]+)="([^"]+)"')
>>> sample = '''\
... "Harry Potter", "book", "12 Mar 2014 note=""good"" language=""English"""
... "Forrest Gump", "movie", "14 March 2015 note=""good"" language=""Aztec"""
... '''
>>> reader = csv.reader(sample.splitlines(True), skipinitialspace=True)
>>> [dict(keyvalue.findall(row[2])) for row in reader]
[{'note': 'good', 'language': 'English'}, {'note': 'good', 'language': 'Aztec'}]

【讨论】:

  • 太棒了,非常感谢。我真的需要研究理解,因为它们似乎是某种巫毒,然后变成了 Graal。
  • @WoJ:列表推导式只是从循环构建列表的捷径。 namedfields = [],然后for row in reader: namedfields.append(dict(keyvalue.findall(row[2]))) 将是显式循环替代方案。
猜你喜欢
  • 1970-01-01
  • 2012-04-25
  • 2018-11-30
  • 2019-05-15
  • 1970-01-01
  • 2016-11-23
  • 1970-01-01
  • 2017-11-30
  • 2019-12-04
相关资源
最近更新 更多