2013-02-19 80 views
4

我有一个庞大的文件,我需要为特定条目提供数据。文件结构是:提取两个符号之间的多行数据 - 正则表达式和Python3

>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的记录,而不是使用条目名称> Entry1.1'直到下一个>>'作为REGEX中的标记来提取它们之间的行。但我不知道如何构建这样复杂的REGEX表达式。一旦我有这样的表情我就会把它FOR循环:

For entry in entrylist: 
    GET record from big_file 
    DO some processing 
    WRITE in result file 

什么可以进行记录的这种提取特定条目正则表达式?有没有更多的pythonic方式来实现这一目标?我很感谢你对此的帮助。

AK

+0

啊谢谢。我没有看到你看到我的答案。如果您需要改进,请询问。例如,有趣的是,用户可以输入** 1 1 **而不是** 1.1 ** – eyquem 2013-02-19 20:33:21

回答

4

用正则表达式

说明的
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)

%s接收项的参考:1.1,2,2.1等

2)

部分(?![^\n]+?\d)是做验证。

(?![^\n]+?\d)是负先行断言,说什么是后%s一定不能[^\n]+?\d的一个数字\d

我写[^\n]之前说的任何字符[^\n]+?表示“任何换行符以外的\n ”。
我不得不写这个,而不是简单的.+?,因为我把国旗re.DOTALL和模式部分.+?将采取行动,直到条目结束。
不过,我只是想验证输入的参考(%s所的模式表示)后,不会有该行的结束前补充位数,由输入错误

所有这一切是因为如果有一个Entry2.1但没有Entry2,并且用户只输入2,因为他想要Entry2而没有其他的,正则表达式会检测Entry2.1的存在并且会产生它,尽管用户实际上真的很喜欢Entry2。

3)

截至'(>Entry *%s(?![^\n]+?\d).+?)末,部分.+?将赶上入学的完整块,因为点代表任意字符,包括换行符\n
它是这个目的,我把国旗re.DOTALL为了使下面的图案部分.+?能够通过新行,直到输入的结束。

4)

我想匹配停在入境所需的结束,而不是下一个内部,使得由parenthesises在(>Entry *%s(?![^\n]+?\d).+?)定义的组会赶上正是我们想要
因此,我把在结束了积极查找ahaed断言(?=>|(?:\s*\Z)),指出该角色之前将运行ungreedy .+?必须停止,以配合或者是>(下一个条目的开头)或字符串\Z结束。
因为它有可能是最后一项结束将不完全是整个字符串的结尾,我把\s*,意思是“可能的空格结束前后”。
所以\s*\Z的意思是“可以有空格前碰到的字符串的结尾” 空格被一个blank\f\n\r\t\v

+0

谢谢...像一个魅力工作.... – Bade 2013-02-19 20:17:21

+1

谢谢。请注意,我使用'found = re.findall(patbase%x,ss,re.DOTALL)',认为可能会有几个Entry具有相同的引用。如果不是的话,你应当以书面形式直接''打印简化代码 '\ n%S \ n' %re.search(patbase%×,SS,re.DOTALL)。集团()'' - 了' '打印'发现==',发现''是一个煤渣没有需要 – eyquem 2013-02-19 20:44:01

0

不完全确定你在问什么。这会让你更接近吗?它将把你的所有条目作为字典键和所有条目的列表。假设它的格式就像我相信的那样。它是否有重复的条目?下面是我得到了什么:

entries = {} 
key = '' 
for entry in open('entries.txt'): 
    if entry.startswith('>Entry'): 
     key = entry[1:].strip() # removes > and newline 
     entries[key] = [] 
    else: 
     entries[key].append(entry) 
+0

如果我不够清楚,我很抱歉。实际上文件太大(〜1GB),所以我只想要一个字符串匹配而不是提取条目。 'eyquem'的回答很好地完成了这项工作。 – Bade 2013-02-19 20:19:37

+0

这很好。无需道歉:-)抱歉,我无法提供更多帮助。 – Hoopdady 2013-02-19 20:25:34

+1

@Atul如果该文件是非常大的,它可能是有问题的使用正则表达式,因为它需要加载的文件的全部内容到内存中。通过使用正则表达式块浏览文件需要一些棘手的过程,因为如果块本身不重叠,用正则表达式搜索的文本的期望部分可以重叠在两个块上。我清楚了吗? – eyquem 2013-02-19 20:48:13

1

我不好用正则表达式,所以我尽量尽可能寻找非正则表达式解决方案。在Python中,存储迭代逻辑的天然场所是发电机,所以我会用这样的(无itertools要求的版本):

def group_by_marker(seq, marker): 
    group = [] 
    # advance past negatives at start 
    for line in seq: 
     if marker(line): 
      group = [line] 
      break 
    for line in seq: 
     # found a new group start; yield what we've got 
     # and start over 
     if marker(line) and group: 
      yield group 
      group = [] 
     group.append(line) 
    # might have extra bits left.. 
    if group: 
     yield group 

在您的例子情况下,我们得到:

>>> with open("entry0.dat") as fp: 
...  marker = lambda line: line.startswith(">Entry") 
...  for group in group_by_marker(fp, marker): 
...   print(repr(group[0]), len(group)) 
...   
'>Entry1.1\n' 10 
'>Entry2.1\n' 9 
'>Entry3.2\n' 4 

这种方法的一个优点是我们永远不必在内存中保留多个组,所以它对于真正的大文件很方便。它并不像正则表达式那样快,但如果文件是1 GB,那么无论如何你都可能会受到I/O限制。

+0

非常好,谢谢! ~~我想知道,我们如何才能在Python 3上完成这项工作?编辑:nevermind,不知何故,我确实在Python 2上得到了输出,但在3上没有输出,但毕竟它在Python 3上工作。 – arjan 2016-03-16 14:39:15

相关问题