Вопрос

У меня есть строка, как следующее:

<118>date=2010-05-09,time=16:41:27,device_id=FE-2KA3F09000049,log_id=0400147717,log_part=00,type=statistics,subtype=n/a,pri=information,session_id=o49CedRc021772,from="prvs=4745cd07e1=example@example.org",mailer="mta",client_name="example.org,[194.177.17.24]",resolved=OK,to="example@example.org",direction="in",message_length=6832079,virus="",disposition="Accept",classifier="Not,Spam",subject="=?windows-1255?B?Rlc6IEZ3OiDg5fDp5fog+fno5fog7Pf46eHp7S3u4+Tp7SE=?="

Я пытался использовать модуль CSV, и он не подходил, потому что я не нашел способ игнорировать то, что цитируется. Pyparsing выглядел как лучший ответ, но я не нашел способ объявить все грамматики.

В настоящее время я использую свой старый сценарий Perl, чтобы разбирать его, но я хочу, чтобы это написано в Python. Если вам нужен мой фрагмент Perl, я буду рад предоставить это.

Любая помощь ценится.

Это было полезно?

Решение

Я не уверен, что вы действительно ищете, но

import re
data = "date=2010-05-09,time=16:41:27,device_id=FE-2KA3F09000049,log_id=0400147717,log_part=00,type=statistics,subtype=n/a,pri=information,session_id=o49CedRc021772,from=\"prvs=4745cd07e1=example@example.org\",mailer=\"mta\",client_name=\"example.org,[194.177.17.24]\",resolved=OK,to=\"example@example.org\",direction=\"in\",message_length=6832079,virus=\"\",disposition=\"Accept\",classifier=\"Not,Spam\",subject=\"=?windows-1255?B?Rlc6IEZ3OiDg5fDp5fog+fno5fog7Pf46eHp7S3u4+Tp7SE=?=\""
pattern = r"""(\w+)=((?:"(?:\\.|[^\\"])*"|'(?:\\.|[^\\'])*'|[^\\,"'])+)"""
print(re.findall(pattern, data))

дает тебе

[('date', '2010-05-09'), ('time', '16:41:27'), ('device_id', 'FE-2KA3F09000049'),
 ('log_id', '0400147717'), ('log_part', '00'), ('type', 'statistics'),
 ('subtype', 'n/a'), ('pri', 'information'), ('session_id', 'o49CedRc021772'),
 ('from', '"prvs=4745cd07e1=example@example.org"'), ('mailer', '"mta"'),
 ('client_name', '"example.org,[194.177.17.24]"'), ('resolved', 'OK'),
 ('to', '"example@example.org"'), ('direction', '"in"'),
 ('message_length', '6832079'), ('virus', '""'), ('disposition', '"Accept"'),
 ('classifier', '"Not,Spam"'), 
 ('subject', '"=?windows-1255?B?Rlc6IEZ3OiDg5fDp5fog+fno5fog7Pf46eHp7S3u4+Tp7SE=?="')
]

Возможно, вы захотите убрать цитируемые строки потом (используя mystring.strip("'\"")).

РЕДАКТИРОВАТЬ: Это регулярное выражение также правильно обрабатывает сбежавшие цитаты внутри цитируемых строк (a="She said \"Hi!\"").

Объяснение Regex:

(\w+)=((?:"(?:\\.|[^\\"])*"|'(?:\\.|[^\\'])*'|[^\\,"'])+)

(\w+): Сопоставьте идентификатор и запечатлеть его в отсрочку №. 1.

=: Матч А. =

(: Захватите следующие в обратную силу нет. 2:

(?:: Одно из следующих:

"(?:\\.|[^\\"])*": Двойная цитата, сопровождаемая нулю или более из следующего: сбежаемый символ или нецитатовый / не обратный символ, а затем другой двойной цитату

|: или

'(?:\\.|[^\\'])*': См. Выше, просто для одиночных кавычек.

|: или

[^\\,"']: Один символ, который не является ни обратной косой, запятой, ни цитатой.

)+: Повторите хотя бы один раз, столько раз, насколько это возможно.

): конец сборной группы нет. 2

Другие советы

Возможно, лучше использовать существующий парсер, чем использовать Ad-Hoc Regexs.

PARSE_HTTP_LIST (S) Списки анализа, как описано в разделе RFC 2068. 2. В частности, развертываемые запятыми на тарифах, где элементы списка могут включать цитируемые строки. Цитируемая строка может содержать запятую. Нецируемая строка может иметь цитаты посередине. Ни запяты, ни цитаты считают, если они сбежались. Только двойные цитаты, а не однозначные цитаты. PARSE_KEQV_LIST (L) Список анализов ключа = Значение строк, где ключи не дублируются.

Пример:

>>> pprint.pprint(urllib2.parse_keqv_list(urllib2.parse_http_list(s)))
{'<118>date': '2010-05-09',
 'classifier': 'Not,Spam',
 'client_name': 'example.org,[194.177.17.24]',
 'device_id': 'FE-2KA3F09000049',
 'direction': 'in',
 'disposition': 'Accept',
 'from': 'prvs=4745cd07e1=example@example.org',
 'log_id': '0400147717',
 'log_part': '00',
 'mailer': 'mta',
 'message_length': '6832079',
 'pri': 'information',
 'resolved': 'OK',
 'session_id': 'o49CedRc021772',
 'subject':'=?windows-1255?B?Rlc6IEZ3OiDg5fDp5fog+fno5fog7Pf46eHp7S3u4+Tp7SE=?=',
 'subtype': 'n/a',
 'time': '16:41:27',
 'to': 'example@example.org',
 'type': 'statistics',
 'virus': ''}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top