使用Python分析文本文件

2024-03-29 13:43:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我对Python很陌生,希望使用它来解析文本文件。文件有250-300行以下格式:

---- Mark Grey (mark.grey@gmail.com) changed status from Busy to Available @ 14/07/2010 16:32:36 ----
----  Silvia Pablo (spablo@gmail.com) became Available @ 14/07/2010 16:32:39 ----

对于此文件中的所有条目,我需要将以下信息存储到另一个文件(excel或文本)中

UserName/ID  Previous Status New Status Date Time

所以我的结果文件应该是这样的

Mark Grey/mark.grey@gmail.com  Busy Available 14/07/2010 16:32:36
Silvia Pablo/spablo@gmail.com  NaN  Available 14/07/2010 16:32:39

提前谢谢你

任何帮助都将不胜感激


Tags: 文件comstatusgmailgreyavailablepablomark
3条回答

两种重新的兴趣模式似乎是…:

p1 = r'^---- ([^(]+) \(([^)]+)\) changed status from (\w+) to (\w+) (\S+) (\S+) ----$'
p2 = r'^---- ([^(]+) \(([^)]+)\) became (\w+) (\S+) (\S+) ----$'

所以我会:

import csv, re, sys

# assign p1, p2 as above (or enhance them, etc etc)

r1 = re.compile(p1)
r2 = re.compile(p2)
data = []

with open('somefile.txt') as f:
    for line in f:
        m = p1.match(line)
        if m:
            data.append(m.groups())
            continue
        m = p2.match(line)
        if not m:
            print>>sys.stderr, "No match for line: %r" % line
            continue
        listofgroups = m.groups()
        listofgroups.insert(2, 'NaN')
        data.append(listofgroups)

with open('result.csv', 'w') as f:
    w = csv.writer(f)
    w.writerow('UserName/ID Previous Status New Status Date Time'.split())
    w.writerows(data)

如果我描述的这两种模式不够通用,当然可能需要对它们进行调整,但我认为这种通用方法将是有用的。虽然许多使用堆栈溢出的Python用户非常不喜欢REs,但我发现它们对于这种实用的即席文本处理非常有用。

也许其他人想使用REs来实现一些荒谬的用途,比如对CSV、HTML、XML的特殊解析。。。--还有许多其他类型的结构化文本格式,它们都有非常好的解析器!而且,其他任务远远超出REs的“舒适区”,需要像pyparsing这样的可靠的通用解析器系统。或者在另一个极端的超级简单的任务中,使用简单的字符串做得非常好(例如,我记得最近的一个SO问题使用if re.search('something', s):,而不是if 'something' in s:!-).

但是对于REs适用的相当广泛的任务(不包括一端最简单的任务,另一端解析结构化的或有点复杂的语法),使用它们并没有什么错,我建议所有程序员至少学习REs的基础知识。

import re

pat = re.compile(r"----\s+(.*?) \((.*?)\) (?:changed status from (\w+) to|became) (\w+) @ (.*?) ----\s*")
with open("data.txt") as f:
    for line in f:
        (name, email, prev, curr, date) = pat.match(line).groups()
        print "{0}/{1}  {2} {3} {4}".format(name, email, prev or "NaN", curr, date)

这就假设了空白,并且假设每一行都符合模式。如果您想优雅地处理脏输入,可能需要添加错误检查(例如检查pat.match()不返回None)。

开始:

result = []
regex = re.compile(
    r"""^-*\s+
    (?P<name>.*?)\s+
    \((?P<email>.*?)\)\s+
    (?:changed\s+status\s+from\s+(?P<previous>.*?)\s+to|became)\s+
    (?P<new>.*?)\s+@\s+
    (?P<date>\S+)\s+
    (?P<time>\S+)\s+
    -*$""", re.VERBOSE)
with open("inputfile") as f:
    for line in f:
        match = regex.match(line)
        if match:
            result.append([
                match.group("name"),
                match.group("email"),
                match.group("previous")
                # etc.
            ])
        else:
            # Match attempt failed

会给你一组匹配的部分。然后我建议您使用^{}以标准格式存储结果。

相关问题 更多 >