регулярные выражения Python, возвращать только первое совпадение - PullRequest
0 голосов
/ 11 января 2019

Я пытаюсь вернуть только первое совпадение из приведенной ниже переменной

MACHINE: p1prog06<br>

MACHINE: p1prog06

используя следующее выражение:

res = list(set([re.sub(r'=(?:\^M)?|[\r\n]+', '', m.group(1)) for m in re.finditer(r'\bMACHINE:\s*(.*(?:(?:\r\n?|\n)\S+)?)', email_body, re.M)]))

Согласно документации,

`list(set(res))`   

должен возвращать уникальные значения, но я получаю

u'p1prog06', u'p1prog06<br><br>']

Код:

conn = imaplib.IMAP4_SSL("outlook.office365.com")
conn.login(user,pwd)
conn.select("test")

resp, items = conn.uid("search" ,None, '(OR (FROM "email@pexample.com) (FROM "email2@pexample.com"))')



items = items[0].split()
for emailid in items:
    resp, data = conn.uid("fetch",emailid, "(RFC822)")
    if resp == 'OK':
        email_body = data[0][1].decode('utf-8')
        mail = email.message_from_string(email_body)
        #get all emails with words "PA1" or "PA2" in subject
        if mail["Subject"].find("PA1") > 0 or mail["Subject"].find("PA2") > 0:
                  #search email body for job name (string after word "JOB")
          regex1 = r'(?<!^)JOB:\s*(\S+)'
          #regex2 = r'\bMACHINE:\s*(.*(?:\s*^\d+)?)'
          #c=re.searchall(regex2, email_body, re.M)#,re.DOTALL)
          a=re.findall(regex1 ,email_body)
          #res = [re.sub(r'=(?:\^M)?|[\r\n]+', '', m.group(1)) for m in re.finditer(r'\bMACHINE:\s*(.*(?:(?:\r\n?|\n)\S+)?)', email_body, re.M)]
          res = list(set([re.sub(r'=(?:\^M\<br><br>)?|[\r\n]+', '', m.group(1)) for m in re.finditer(r'\bMACHINE:\s*(.*(?:(?:\r\n?|\n)\S+)?)', email_body, re.M)]))

Ответы [ 3 ]

0 голосов
/ 11 января 2019

Если вы хотите, вы можете улучшить свое регулярное выражение до это :

\bMACHINE:\s*([^<]*(?:(?:\r\n?|\n)\S+)?)

Теперь ваше регулярное выражение остановится на знаке <.

0 голосов
/ 11 января 2019

Ваше основное регулярное выражение, используемое в re.finditer совпадениях <br> тегов. Все, что вам нужно, это удалить их с помощью re.sub:

re.sub(r'=(?:\^M)?|<br\s*(?:/\s*)?>|[\r\n]+', '', m.group(1))
                   ^^^^^^^^^^^^^^^^ 

Вы также можете использовать его с re.findall следующим образом:

res = list(set([re.sub(r'=(?:\^M)?|<br\s*(?:/\s*)?>|[\r\n]+', '', m) for m in re.findall(r'\bMACHINE:\s*(.*(?:(?:\r\n?|\n)\S+)?)', email_body)]))

Примечание re.M является избыточным и удаляется.

Шаблон <br\s*(?:/\s*)?> соответствует <br, затем \s* соответствует 0+ пробелов, (?:/\s*)? соответствует противоположной последовательности / и 0+ пробелов, и > наконец соответствует >. Таким образом, он может соответствовать <br/>, <br>, <br /> и даже <br / >.

0 голосов
/ 11 января 2019

Как отмечается в комментарии, ваши примеры не уникальны, поэтому функциональность кажется правильной. Либо добавьте термин в метод sub, чтобы удалить теги <br> (и тогда ваша команда set удалит дублирующиеся записи). Или, если вы хотите получить только первое совпадение из email_body, попробуйте просто использовать метод search в пакете регулярных выражений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...