2017-10-06 1 views
2

Ich habe eine E-Mail-Protokolldatei, die wie folgt lautet:Aufnahme wiederholt Gruppen in Python Regex

Aug 15 00:01:06 **** sm-mta*** to=<[email protected]>,<[email protected]>,[email protected], some_more_stuff 
Aug 16 13:16:09 **** sendmail*** to=<[email protected]>, some_more_stuff 
Aug 17 11:14:48 **** sm-mta*** to=<[email protected]>,<[email protected]>, some_more_stuff 

Was ich will, ist eine Liste aller Mail-Hosts in Zeilen, die „sm-mta“ enthalten. In diesem Fall wäre das: ['gmail.com', 'yahoo.com', 'aol.com', 'gmail.com', gmail.com']

re.findall(r'sm-mta.*[email protected](.*?)[>, ]') nur erste Host jeder passende Zeile zurück (['gmail.com','gmail.com'])

re.findall(r'[email protected](.*?)[>, ]') die korrekte Liste zurückkehren, aber ich brauche zu filtern. Gibt es eine Problemumgehung dafür?

+0

können Sie versuchen, dieses https://eval.in/875159 –

Antwort

1

Wenn Sie nicht PyPI regex-Bibliothek verwenden können, werden Sie zu tun haben, dass in zwei Schritten: 1) greifen die Linien mit sm-mta und 2) greifen die Werte, die Sie benötigen, mit so etwas wie

import re

txt="""Aug 15 00:01:06 **** sm-mta*** to=<[email protected]>,<[email protected]>,[email protected], some_more_stuff 
Aug 16 13:16:09 **** sendmail*** to=<[email protected]>, some_more_stuff 
Aug 17 11:14:48 **** sm-mta*** to=<[email protected]>,<[email protected]>, some_more_stuff""" 
rx = r'@([^\s>,]+)' 
filtered_lines = [x for x in txt.split('\n') if 'sm-mta' in x] 
print(re.findall(rx, " ".join(filtered_lines))) 

Siehe die Python demo online. Das Muster @([^\s>,]+) stimmt mit @ überein und erfasst und gibt alle 1+ Zeichen außer Leerzeichen, > und , zurück.

Wenn Sie PyPI regex Bibliothek verwenden können, können Sie die Liste der Strings bekommen können Sie mit

brauchen
>>> import regex 
>>> x="""Aug 15 00:01:06 **** sm-mta*** to=<[email protected]>,<[email protected]>,[email protected], some_more_stuff 
Aug 16 13:16:09 **** sendmail*** to=<[email protected]>, some_more_stuff 
Aug 17 11:14:48 **** sm-mta*** to=<[email protected]>,<[email protected]>, some_more_stuff""" 
>>> rx = r'(?:^(?=.*sm-mta)|\G(?!^)).*[email protected]\K[^\s>,]+' 
>>> print(regex.findall(rx, x, regex.M)) 
['gmail.com', 'yahoo.com', 'aol.com,', 'gmail.com', 'gmail.com'] 

Siehe the Python online demo und regex demo.

Muster Details

  • (?:^(?=.*sm-mta)|\G(?!^)) - eine Linie, die sm-mta Teilzeichenfolge nach irgendwelchen 0+ Zeichen außer Zeilenumbruch Zeichen hat, oder die Stelle, wo das vorherige Spiel
  • .*[email protected] beendet - alle 0+ Zeichen andere als Zeilenumbruch Zeichen, so wenig wie möglich, bis zu @ und @ selbst
  • \K - ein Match-Reset-Operator, der den gesamten Text so weit in der aktuellen ablegt mieten Iteration
  • [^\s>,]+-1 oder mehr Zeichen außer Leerzeichen, , und >
3

Versuchen Sie regex Modul.

x="""Aug 15 00:01:06 **** sm-mta*** to=<[email protected]>,<[email protected]>,[email protected], some_more_stuff 
Aug 16 13:16:09 **** sendmail*** to=<[email protected]>, some_more_stuff 
Aug 17 11:14:48 **** sm-mta*** to=<[email protected]>,<[email protected]>, some_more_stuff""" 
import regex 
print regex.findall(r"sm-mta.*to=\K|\G(?!^)[email protected](.*?)[>, ]", x, version=regex.V1) 

Ausgang: ['', 'gmail.com', 'yahoo.com', 'aol.com', '', 'gmail.com', 'gmail.com']

einfach das erste leere Spiel ignorieren.

https://regex101.com/r/7zPc6j/1