2015-06-10 7 views
0

Я использую следующий код Python регулярного выражения для анализа значений из поля сообщения электронной почты:Regex шаблон неожиданного значение

import re 

PATTERN = re.compile(r'''((?:[^(;|,)"']|"[^"]*"|'[^']*')+)''') 
list = PATTERN.split(raw)[1::2] 

Список должны выводить имя и адрес каждого получателя, на основании либо», " или ";" как разделитель. Если эти значения находятся в кавычках, они должны быть проигнорированы, это часть имени, часто: «Фамилия, имя»

В большинстве случаев это работает хорошо, однако в следующем случае я неожиданно поведение:

"Some Name | Company Name" <[email protected]> 

В этом случае он разделяется на "|" персонаж. Несмотря на то, что когда я проверяю шаблон на веб-сайтах регулярных выражений, он выбирает имя и адрес в целом. Что я делаю не так?

Пример входных данных будет:

"Some Name | Company Name" <[email protected]>, "Some Other Name | Company Name" <[email protected]>, "Last Name, First Name" <[email protected]> 
+0

Он нигде не разделяется. Дает мне выход '['« Некоторое имя | Название компании »<имя@example.com>']' – nu11p01n73R

+0

Это правильно, обычно их было бы несколько в строке. Я хочу выделить их. Однако, если я запускаю его в своем движке Google, он разбивается на | – Vincent

ответ

2

Это не является прямым ответом на ваш вопрос но к проблеме, которую вы, кажется, решаете, и поэтому, возможно, по-прежнему полезно:

Чтобы разобрать электронные письма, я всегда широко использую Python's email library.

В вашем случае вы могли бы использовать что-то вроде этого:

from email.utils import getaddresses 
from email import message_from_string 

msg = message_from_string(str_with_msg_source) 
tos = msg.get_all('to', []) 
ccs = msg.get_all('cc', []) 
resent_tos = msg.get_all('resent-to', []) 
resent_ccs = msg.get_all('resent-cc', []) 
all_recipients = getaddresses(tos + ccs + resent_tos + resent_ccs) 
for (name, address) in all_recipients: 
    # do some postprocessing on name or address if necessary 

Это всегда брало надежный уход имен расщепления и адреса в почтовых заголовках в моих случаях.

+0

Правильный инструмент для работы. –

+0

Это кажется отличным предложением. Я использую webhook для анализа электронных писем. Могу ли я также передать значение строки из поля «Кому»? – Vincent

+0

Не уверен, правильно ли я понимаю. Но если вы спросите, можете ли вы использовать это для одиночных строк, то да, конечно, например: 'email.utils.parseaddr (« Mr Smith | Something »<[email protected]>)' дает вам '('Mr Smith | Something ',' [email protected] ') '. – myke

1

Вы можете использовать более простое регулярное выражение, используя внешний вид обходные, чтобы разделить текст.

r'(?<=>)\s*,\s*(?=")' 

Regex Объяснение

  • \s*,\s* матчи ,, который окружен нуля или более пробелов (\s*)

  • (?<=>) Посмотрите за утверждение. Проверяет, предшествует ли ,: >

  • (?=") Посмотрите на утверждение. Проверки, если , сопровождается Теста "

>>> re.split(r'(?<=>)\s*,\s*(?=")', string) 
['"Some Name | Company Name" <[email protected]>', '"Some Other Name | Company Name" <[email protected]>', '"Last Name, First Name" <[email protected]>'] 

коррекций

  • Случай 1 В приведенном выше примере, мы использовали один разделитель , ,Если йо хотите разделить на основе более чем одного разделителей можно использовать символьный класс

    r'(?<=>)\s*[,;]\s*(?=")' 
    
    • [,;] класс символов, соответствует , или ;

  • Корпус 2 As menti oned в комментариях, если адресная часть отсутствует, все, что нам нужно сделать, это добавить " на вид сзади

    Пример

    >>> string = '"Some Other Name | Company Name" <[email protected]>, "Some Name, Nothing", "Last Name, First Name" <[email protected]>' 
    
    >>> re.split(r'(?<=(?:>|"))\s*[,;]\s*(?=")', string) 
    ['"Some Other Name | Company Name" <[email protected]>', '"Some Name, Nothing"', '"Last Name, First Name" <[email protected]>'] 
    
+0

Для этого случая да, но иногда нет имени, а просто «[email protected]» без <>. Поэтому я решил, что нужно будет разделить на всех, или; вне котировок – Vincent

+0

@ Vincent это тоже можно сделать. В этом случае измените внешний вид как '(? <=(> |") 'так, чтобы он искал'> 'или' '' перед ',' – nu11p01n73R

+0

@Vincent. Я добавил редактирование. См. Раздел 2 корпуса. Надеюсь, это то, о чем вы говорите. – nu11p01n73R