我有一个巨大的文件,我需要从中获得特定条目的数据。文件结构为:
>Entry1.1
#size=1688
704 1 1 1 4
979 2 2 2 0
1220 1 1 1 4
1309 1 1 1 4
1316 1 1 1 4
1372 1 1 1 4
1374 1 1 1 4
1576 1 1 1 4
>Entry2.1
#size=6251
6110 3 1.5 0 2
6129 2 2 2 2
6136 1 1 1 4
6142 3 3 3 2
6143 4 4 4 1
6150 1 1 1 4
6152 1 1 1 4
>Entry3.2
#size=1777
AND SO ON-----------
我要实现的是,我需要提取某些条目的所有行(完整记录)。对于e.x.我需要entry1.1的记录,这样我就可以使用entry'>entry1.1'直到下一个'>'的名称作为regex中的标记来提取中间的行。但我不知道如何构建这样复杂的正则表达式。一旦我有了这样的表达式,我就把它设为for循环:
For entry in entrylist:
GET record from big_file
DO some processing
WRITE in result file
regex可以为特定条目执行这样的记录提取吗?还有什么蟒蛇的方法可以达到这个目的吗?我很感激你在这方面的帮助。
AK公司
最佳答案
带正则表达式
import re
ss = '''
>Entry1.1
#size=1688
704 1 1 1 4
979 2 2 2 0
1220 1 1 1 4
1309 1 1 1 4
1316 1 1 1 4
1372 1 1 1 4
1374 1 1 1 4
1576 1 1 1 4
>Entry2.1
#size=6251
6110 3 1.5 0 2
6129 2 2 2 2
6136 1 1 1 4
6142 3 3 3 2
6143 4 4 4 1
6150 1 1 1 4
6152 1 1 1 4
>Entry3.2
#size=1777
AND SO ON-----------
'''
patbase = '(>Entry *%s(?![^\n]+?\d).+?)(?=>|(?:\s*\Z))'
while True:
x = raw_input('What entry do you want ? : ')
found = re.findall(patbase % x, ss, re.DOTALL)
if found:
print 'found ==',found
for each_entry in found:
print '\n%s\n' % each_entry
else:
print '\n ** There is no such an entry **\n'
解释
'(>Entry *%s(?![^\n]+?\d).+?)(?=>|(?:\s*\Z))'
:(一)
接收到条目的引用:1.1、2、2.1等
2个)
部分
%s
将进行验证。(?![^\n]+?\d)
是一个否定的前瞻性断言,它表示在(?![^\n]+?\d)
之后的内容不能是%s
,也就是说在数字[^\n]+?\d
之前的任何字符[^\n]+?
我写
\d
是指“除换行符之外的任何字符”。我不得不写这个而不是简单的
[^\n]
,因为我放置了标志\n
,模式部分.+?
将一直作用到条目的末尾。但是,我只想验证在输入的引用(由模式中的%s表示)之后,行尾之前不会有补充数字,输入错误
所有这些都是因为如果存在entry2.1但没有entry2,并且用户只输入了2因为他想要entry2而没有其他条目,那么regex将检测到entry2.1的存在并将其产生,尽管用户实际上确实希望entry2。
三)
在
re.DOTALL
结束时,部分.+?
将捕获条目的完整块,因为点代表任何字符,由新行组成。为了达到这个目的,我设置了标志
'(>Entry *%s(?![^\n]+?\d).+?)
以便使下面的模式部分.+?
能够传递新行,直到条目结束。(四)
我希望匹配停止在所需条目的末尾,而不是在下一个条目的内部,这样由
\n
中的括号定义的组将准确地捕获我们所需的内容因此,我最后给出了一个积极的观点:AHED断言“cc>”,它表示运行不贪婪的
re.DOTALL
必须停止匹配的字符不是.+?
(下一个条目的开始),也不是字符串(>Entry *%s(?![^\n]+?\d).+?)
的结尾。由于最后一个条目的结尾可能不完全是整个字符串的结尾,所以我将
(?=>|(?:\s*\Z))
放在了“结尾之前可能有空格”。所以
.+?
意味着“在碰到字符串末尾之前可以有空格”空白是a
>
,\Z
,\s*
,\s*\Z
,blank
,\f
,\n