我有一个巨大的文件,我需要从中获得特定条目的数据。文件结构为:

>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*\Zblank\f\n

09-26 01:29