使用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
提前谢谢大家,
任何帮助都非常感谢
6 个回答
6
我们关注的两个正则表达式模式是……:
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)
如果我描述的这两个模式不够通用,当然可以进行一些调整,但我觉得这种大体的方法会很有用。虽然很多在Stack Overflow上的Python用户对正则表达式非常反感,但我觉得它们在处理一些临时文本时非常实用。
也许这种反感是因为有些人想用正则表达式来做一些不合适的事情,比如临时解析CSV、HTML、XML等——这些其实都有很好的解析工具可以使用!还有一些任务超出了正则表达式的“舒适区”,需要用到更强大的解析系统,比如pyparsing。另外,还有一些超级简单的任务,用简单的字符串就能很好地完成(比如我记得最近有个问题用if re.search('something', s):
,而用if 'something' in s:
就能解决了!)
但是对于那些相对广泛的任务(排除最简单的情况和解析结构化或稍微复杂的语法),使用正则表达式其实没有什么问题,我建议所有程序员至少要学会正则表达式的基础知识。
6
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
。
16
为了帮助你入门:
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
这段代码会给你一个匹配结果的数组,里面包含了各个部分。接下来,我建议你使用csv模块
,把结果存储成一个标准格式。