2012-07-10 91 views
1

我在工作中遇到了一个问题,需要我在PostgreSQL数据库中插入一些MASSIVE制表符分隔值文件(将8-15 GB的.txt文件考虑在内),但是我数据格式化的方式首先遇到了问题。基本上,我们获得数据的方式(不幸的是我们无法以更好的格式获取数据),出现一些反斜杠并导致返回/换行。从制表符分隔的值中删除某些返回字符文件

所以,有几行(数据行,tab-delim)被切分成多行,其中第n行的最后一个字符是\,并且第n + 1行的第一个字符是一个制表符。通常n行会被分成1-3行(例如,行n以“\”结尾,行n + 1和n + 2以制表符开头并以“\”结尾,行n + 3开始带有一个标签)。

我需要编写一个脚本,可以与这些巨大的文件(这将运行在具有192 GB的RAM的Linux服务器上运行)寻找以制表符开头的行,然后删除返回(和“ \“无论它存在于何处)并保存文本文件。

回顾一下,客户的日志记录程序将原始行N拆分为行n,n + 1,有时n + 2和n + 3(具体取决于行N中出现多少个\字符),我需要写一个python脚本来重建原始的线N.

+0

发布一个小样本,其中包含任何敏感的编辑内容。预期的投入和产出是说明这种问题的好方法。 – MattH 2012-07-10 14:28:39

回答

0

这是基于@ user665637的很好的答案。

#!/usr/bin/python 

import re, sys 

pat_incomplete = re.compile(r'\\\s*$') 
pat_indented = re.compile(r'^\t') 

try: 
    _, fname_in, fname_out = sys.argv 
except ValueError: 
    print("Usage: python line_joiner.py <input_filename> <output_filename>") 
    sys.exit(1) 

with open(fname_in) as in_f, open(fname_out, "w") as out_f: 
    lines = iter(in_f) 
    try: 
     line = next(lines) 
     s = pat_incomplete.sub('', line) 
    except StopIteration: 
     print("Input file did not contain any data") 
     sys.exit(2) 

    for line in lines: 
     line = pat_incomplete.sub('', line) 
     if pat_indented.match(line): 
      s += pat_indented.sub('',line) 
     else: 
      out_f.write(s) 
      s = line 
    out_f.write(s) 

变化:

  • 使用 “原始字符串” 正则表达式,它们更容易阅读。

  • 从命令行参数中获取输出文件名并写入该文件。打印消息并退出,如果用户提供的参数数量错误。当我们解压sys.argv以获得参数时,我们使用变量名称_作为我们不关心的部分。

  • 不去掉行结尾,所以输出文件将具有与输入文件相同的行尾。 (当加入线时,它当然会剥离线端以进行连接。)

  • 不会从输入中滤除空行。这有点棘手,但通过迭代器并调用next(),它在启动循环之前获得第一个输入行;因此s从有效值开始而不是None开始,我们不必每次测试它是否打印它。原始if lastLine:测试在被剥离的输入行上不仅会保护None的初始值lastLine,而且还会过滤输入中的所有空行。

  • 如果你必须在Python 3.0或Python 2中使用它。6,您不能有一个with声明,它会执行两个open()调用;但您可以将它变成两个嵌套的with语句,每个语句都会执行一个open()

+0

非常感谢!你节省了我大量的时间。让我知道,如果有什么我可以为你做的(慈善机构,你想捐赠什么?等)! – user1514979 2012-07-10 19:20:02

+0

不客气!如果你真的想要给EFF另一个小额捐款,但请不要觉得你必须这样做。 – steveha 2012-07-10 19:20:59

1

不受任何替换 “\ n” 个序列:

In [20]: a="blabla\tblabla\tblabla\\\n\tblabla\tblabla" 

In [21]: print(a) 
blabla blabla blabla\ 
    blabla blabla 

In [22]: a=a.replace('\\\n', '') 

In [23]: print(a) 
blabla blabla blabla blabla blabla 

:)

+0

如承诺的那样,给EFF 10美元: – user1514979 2012-07-10 17:06:33

+0

@ user1514979:如果答案有帮助,您应该注意或接受它。捐款很好,但不能代替这里的习俗。 – 2012-07-10 18:13:48

+0

这不回答这个问题。他具有需要合并的特定格式的输入行,输入文件很大,因此需要逐行读取。 – steveha 2012-07-10 18:22:24

2
#!/usr/bin/python 

import re,sys 

lastLine = None 
incomplete = re.compile("\\\\+$") 
indented = re.compile("^\\t") 

for line in open(sys.argv[1]): 
    line = line.rstrip() 
    line = incomplete.sub("", line) 
    if indented.match(line): 
     lastLine += indented.sub("",line) 
    else: 
     if lastLine: 
      print lastLine 
      lastLine = None 
     lastLine = line 

print lastLine 

基本上,我忽略了\在自选项卡结束在下一行告诉你,无论如何这是一个延续。

+0

非常感谢!如承诺的那样,给EFF 10美元(不太确定如何在评论中直接发布图片,所以这里有一个链接): [link](http://i.imgur.com/V2chc.png) 现在,这段代码好像可以工作,但是我怎样才能让它读取文本文件并保存一个正确的文本文件。换句话说,我会想象使用命令: – user1514979 2012-07-10 17:08:39

+0

<继续...>'python cleanData.py uglyData.tsv'然后将清理过的数据保存在名为uglyData-CLEAN.tsv的文本文件中行呢? – user1514979 2012-07-10 17:14:51

+0

+1为一个很好的答案。我对它做了一些调整并发布了我自己的版本,但是完全赞同源代码。 – steveha 2012-07-10 19:18:20

相关问题