我在工作中遇到了一个问题,要求我将一些MASSIVE标签分隔值文件(比如8-15 GB .txt文件)打印到我的PostgreSQL数据库中,但是我遇到了问题。数据首先被格式化。基本上,我们给出数据的方式(不幸的是我们无法以更好的格式获取数据),会出现一些反斜杠并导致返回/换行。
因此,有一些行(数据行,制表符分隔符)被切割成多行,其中行n的最后一个字符是\,行n + 1的第一个字符是制表符。通常行n将被分解为1-3个额外的行(例如,行n以“\”结尾,行n + 1和n + 2以制表符开头,以“\”结束,行n + 3开始用标签)。
我需要编写一个可以处理这些巨大文件的脚本(这将在具有192 GB RAM的Linux服务器上运行)来查找以tab开头的行,然后删除返回(和“\ “无论它存在于何处”并保存文本文件。
总结一下,客户的日志记录程序将原始行N分为行n,n + 1,有时n + 2和n + 3(取决于行N中出现的\ n \ n \ n \ n \ n \ n字符数),我需要编写用于重新创建原始行N的python脚本。
答案 0 :(得分: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
基本上,我忽略了\,因为下一行的标签告诉你它仍然是一个延续。
答案 1 :(得分: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
:)
答案 2 :(得分: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()
。