Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中对正则表达式匹配中的唯一值进行排序_Python_Regex_String Parsing - Fatal编程技术网

在python中对正则表达式匹配中的唯一值进行排序

在python中对正则表达式匹配中的唯一值进行排序,python,regex,string-parsing,Python,Regex,String Parsing,我正在尝试解析日志文件以提取电子邮件地址。 我能够匹配电子邮件并在正则表达式的帮助下打印它。 我注意到我的日志文件中有两封重复的电子邮件。你能帮我弄清楚如何删除重复项并根据匹配的模式只打印唯一的电子邮件地址吗 以下是我迄今为止编写的代码: import sys import re file = open('/Users/me/Desktop/test.txt', 'r') temp =[] for line in file.readlines(): if '->' in line

我正在尝试解析日志文件以提取电子邮件地址。 我能够匹配电子邮件并在正则表达式的帮助下打印它。 我注意到我的日志文件中有两封重复的电子邮件。你能帮我弄清楚如何删除重复项并根据匹配的模式只打印唯一的电子邮件地址吗

以下是我迄今为止编写的代码:

import sys
import re

file = open('/Users/me/Desktop/test.txt', 'r')
temp =[]
for line in file.readlines():
    if '->' in line:
        temp = line.split('->')
    elif '=>' in line:
        temp = line.split('=>')

    if temp:
        #temp[1].strip()
        pattern = re.match('^\x20\w{1,}@\w{1,}\.\w{2,3}\x20?', str(temp[1]), re.M)
        if pattern is not None:
            print pattern.group()

        else:
            print "nono"
下面是我试图解析的示例日志文件:

二月24日00:00:23 smtp1.mail.net进出口[5660]:2014-02-24 00:00:23 1Wuniq邮件idSo Fg->someuser@somedomain.comR=邮件T=远程\u smtp H=smtp.mail.net[000.00.34.17]

二月24日00:00:23 smtp1.mail.net进出口[5660]:2014-02-24 00:00:23 1Wuniq邮件idSo Fg->someuser@somedomain.comR=邮件T=远程\u smtp H=smtp.mail.net[000.00.34.17]

二月24日00:00:23 smtp1.mail.net进出口[5661]:2014-02-24 00:00:23 1Wuniq-mail-idSm-1h=>someuser@somedomain.comR=邮件T=pop_邮件网 H=mta.mail.net[000.00.34.6]

二月24日00:00:23 smtp1.mail.net进出口[5661]:2014-02-24 00:00:23 1Wuniq-mail-idSm-1h=>me@somedomain.comR=邮件T=pop_邮件网 H=mta.mail.net[000.00.34.6]

二月24日00:00:23 smtp1.mail.net进出口[5661]:2014-02-24 00:00:23 1Wuniq-mail-idSm-1h=>wo@somedomain.comR=邮件T=pop_邮件网 H=mta.mail.net[000.00.34.6]

二月24日00:00:23 smtp1.mail.net进出口[5661]:2014-02-24 00:00:23 1Wuniq-mail-idSm-1h=>lol@somedomain.comR=邮件T=pop_邮件网 H=mta.mail.net[000.00.34.6]

二月24日00:00:23 smtp1.mail.net进出口[5661]:2014-02-24 00:00:23 1 Wuniq-mail-idSm-1h已完成

此外,我很好奇我是否能改进我的程序或正则表达式。任何建议都会很有帮助


提前感谢。

您可以使用
集合
容器来保存唯一的结果,每次您想要打印匹配的电子邮件时,您可以检查集合中是否不存在该邮件,然后打印:

import sys
import re

file = open('/Users/me/Desktop/test.txt', 'r')
temp =[]
seen = set()
for line in file.readlines():
    if '->' in line:
        temp = line.split('->')
    elif '=>' in line:
        temp = line.split('=>')

    if temp:
        #temp[1].strip()
        pattern = re.match('^\x20\w{1,}@\w{1,}\.\w{2,3}\x20?', str(temp[1]), re.M)
        if pattern is not None:
            matched =  pattern.group()
            if matched not in seen:
               print matched 

        else:
            print "nono"
正如(他是第一个)所说的,他会成功的

试试这个:

from __future__ import print_function

import re

with open('test.txt') as f:
    data = f.read().splitlines()

emails = set(re.sub(r'^.*\s+(\w+\@[^\s]*?)\s+.*', r'\1', line) for line in data if '@' in line)

print('\n'.join(emails)) if len(emails) else print('nono')
输出:

lol@somedomain.com
me@somedomain.com
someuser@somedomain.com
wo@somedomain.com

PS您可能需要进行适当的电子邮件RegExp检查,因为我使用了非常原始的检查

一些重复项是由于代码中的错误造成的,您在处理每一行时没有重置
temp
。如果一行既不包含
->
也不包含
=>
,并且前面有一行包含这两个字符串中的任何一个,则该行将触发
if temp:
测试,并从前一行输出电子邮件地址(如果有)

当行既不包含
->
也不包含
=>
时,可以通过使用
continue
跳回循环的开始来修复此问题

对于由于同一电子邮件地址出现在多行中而出现的其他真实副本,您可以使用
将其过滤掉

import sys
import re

addresses = set()
pattern = re.compile('^\x20\w{1,}@\w{1,}\.\w{2,3}\x20?')

with open('/Users/me/Desktop/test.txt', 'r') as f:
    for line in f:
        if '->' in line:
            temp = line.split('->')
        elif '=>' in line:
            temp = line.split('=>')
        else:
            # neither '=>' nor '->' present in the line
            continue

        match = pattern.match(temp[1])
        if match is not None:
            addresses.add(match.group())
        else:
            print "nono"

for address in sorted(addresses):
    print(address)
这些地址存储在一个集合中,以删除重复的地址。然后对它们进行分类和打印。还请注意使用
with
语句在上下文管理器中打开文件。这保证了文件将始终处于关闭状态

此外,由于您将多次应用相同的正则表达式模式,因此为了提高效率,提前编译它是值得的

使用正确编写的正则表达式模式,您的代码可以大大简化:

import re

addresses = set()
pattern = re.compile(r'[-=]> +(\w{1,}@\w{1,}\.\w{2,3})')

with open('test.txt', 'r') as f:
    for line in f:
        match = pattern.search(line)
        if match:
            addresses.add(match.groups()[0])

for address in sorted(addresses):
    print(address)

您可以将结果存储在
集合中
集合中
不允许重复项您希望在输出中包含哪些内容?您可以发布预期的输出吗?@MaxU当前我的脚本从日志文件的每一行提取电子邮件地址。我试图只存储唯一的电子邮件地址(最终结果不应该有任何重复的电子邮件地址)。难怪我得到了比日志文件中的实际计数更多的重复。谢谢你指出这个错误。正在测试解决方案:)。干杯@abhinavsingh:我使用了更具针对性的正则表达式模式,用简化的代码进行了更新。新的简化代码显然更有意义,简化了脚本。感谢您的帮助:)