我有一个包含以下数据的文本文件:
Schema:
Column Name Localized Name Type MaxLength
---------------------------- ---------------------------- ------ ---------
Raw Binary Binary 16384
Row 1:
Binary:
-----BEGIN-----
fdsfdsfdasadsad
fsdfafsdafsadfa
fsdafadsfadsfdsa
-----END-----
Row 2:
Binary:
-----BEGIN-----
fsdfdssd
fdsfadsfasd
fsdafdsa
-----END-----
Row 3:
Binary:
-----BEGIN-----
fsdafadsds
fsdafasdsda
fdsafadssad
-----END-----
我需要将“----- BEGIN -----”和“------ END -----”分隔符之间的数据提取到数组中。
这是我尝试过的:
data = open("test_data.txt", 'r')
result = [line.split('-----BEGIN-----') for line in data.readlines()]
print data
然而,这显然会在'----- BEGIN -----'分隔符之后得到所有数据。
如何添加结束分隔符?
请注意,该文件非常大,约为1GB。
答案 0 :(得分:3)
对于之间的多行,您希望将数据分成几个部分,只需捕获以----- BEGIN-开头的每个块,并继续添加行,直至到达END
:
with open("file.txt") as f:
out = []
for line in f:
if line.rstrip() == "-----BEGIN-----":
tmp = []
for line in f:
if line.rstrip() == "-----END-----":
out.append(tmp)
break
tmp.append(line)
这些部分将拆分为子列表:
[['fdsfdsfdasadsad\n', 'fsdfafsdafsadfa\n', 'fsdafadsfadsfdsa\n'], ['fsdfdssd\n', 'fdsfadsfasd\n', 'fsdafdsa \n'], ['fsdafadsds\n', 'fsdafasdsda\n', 'fdsafadssad\n']]
使用with
打开文件,除非您需要列表,否则不要调用读取行,您可以如上所述迭代文件对象而不将所有内容存储在内存中。
或使用itertools.takewhile
获取部分:
from itertools import takewhile, imap
with open("file.txt") as f:
f = imap(str.rstrip,f) # use map for python3
out = [list(takewhile(lambda x: x != "-----END-----",f)) for line in f if line == "-----BEGIN-----"]
print(out)
[['fdsfdsfdasadsad', 'fsdfafsdafsadfa', 'fsdafadsfadsfdsa'],
['fsdfdssd', 'fdsfadsfasd', 'fsdafdsa'],
['fsdafadsds', 'fsdafasdsda', 'fdsafadssad']]
如果您想要一个可以链接的所有单词的列表:
from itertools import takewhile,chain, imap
with open("file.txt") as f:
f = imap(str.rstrip,f)
out = chain.from_iterable(takewhile(lambda x: x != "-----END-----",f) for line in f if line == "-----BEGIN-----")
print(list(out))
['fdsfdsfdasadsad', 'fsdfafsdafsadfa', 'fsdafadsfadsfdsa',
'fsdfdssd', 'fdsfadsfasd', 'fsdafdsa', 'fsdafadsds', 'fsdafasdsda', 'fdsafadssad']
一个文件对象返回它自己的迭代器,所以每当我们迭代或调用takewhile时我们消耗行,takewhile将继续占用行直到我们点击-----END----
然后我们继续迭代直到我们点击另一个-----BEGIN-----
行,如果这些行始终以-
开头且没有其他行,那么您可以检查该条件,即if line[0] == "-"
和x[0] != "-"
,而不是检查整行。
如果您想处理每个部分,可以使用生成器表达式并处理每个部分的行:
with open("file.txt") as f:
f = imap(str.rstrip,f)
out = ((takewhile(lambda x: x != "-----END-----",f)) for line in f if line == "-----BEGIN-----")
for sec in out:
print(list(sec))
['fdsfdsfdasadsad', 'fsdfafsdafsadfa', 'fsdafadsfadsfdsa']
['fsdfdssd', 'fdsfadsfasd', 'fsdafdsa']
['fsdafadsds', 'fsdafasdsda', 'fdsafadssad']
如果您想要一个字符串调用join:
with open("file.txt") as f:
f = imap(str.rstrip,f)
st, end = "-----BEGIN-----", "-----END-----"
out = "".join(chain.from_iterable(takewhile(lambda x: x != end,f)
for line in f if line == st))
print(out)
输出:
fdsfdsfdasadsadfsdfafsdafsadfafsdafadsfadsfdsafsdfdssdfdsfadsfasdfsdafdsafsdafadsdsfsdafasdsdafdsafadssad
要获得保持-----BEGIN-----
和-----END-----
with open("out.txt") as f:
f = imap(str.rstrip,f)
st, end = "-----BEGIN-----", "-----END-----"
out = "".join(["{}{}{}".format(st, "".join(takewhile(lambda x: x != end, f)), end)
for line in f if line == st])
输出:
-----BEGIN-----fdsfdsfdasadsadfsdfafsdafsadfafsdafadsfadsfdsa-----END----------BEGIN-----fsdfdssdfdsfadsfasdfsdafdsa-----END----------BEGIN-----fsdafadsdsfsdafasdsdafdsafadssad-----END-----
答案 1 :(得分:1)
试试这个:
array1 =[]
with open('test_data.txt','r') as infile:
copy = False
for line in infile:
if line.strip() == "-----BEGIN-----":
copy = True
elif line.strip() == "-----END-----":
copy = False
elif copy:
array1.append(line)
这将解决您的目的。
答案 2 :(得分:1)
如果你的文件小到足以将整个内容加载到内存中,那么使用正则表达式(又名正则表达式)可能是最好的方法。
import re
beginstr = '\n-----BEGIN-----\n'
endstr = '-----END-----\n'
pat = re.compile(beginstr + '(.*?\n)' + endstr, re.DOTALL)
with open('test_data.txt', 'r') as f:
data = f.read()
result = pat.findall(data)
for row in result:
print repr(row)
<强>输出强>
'fdsfdsfdasadsad\nfsdfafsdafsadfa\nfsdafadsfadsfdsa\n'
'fsdfdssd\nfdsfadsfasd\nfsdafdsa \n'
'fsdafadsds\nfsdafasdsda\nfdsafadssad\n'
该代码创建一个已编译的正则表达式模式;在这种情况下,它并不是绝对必要的,因为我们只使用了一次模式,但它确实使代码看起来更整洁,恕我直言。
该正则表达式查找由'beginstr'
和'\n' + endstr
分隔的子字符串。由于使用了分组括号,findall
调用仅捕获这些分隔符之间的内容。我在这些括号中放了一个'\n'
,以便捕获的子字符串总是有一个尾随换行符。
答案 3 :(得分:0)
您可以使用itertools.ifilter
:
from itertools import ifilter
with open('a1.txt') as f,open('a1.txt') as g :
f.next()
it=f
print [i.strip() for i in ifilter(lambda x:next(f).strip()=='-----END-----',g)]
结果:
['fdsfdsfdasadsad', 'fsdfdssd', 'fsdafadsds']
如果文件不是很大,请使用re.findall
:
>>> re.findall('-----BEGIN-----\n(.*?)\n-----END-----',open('file_name').read(),re.M|re.DOTALL)
['fdsfdsfdasadsad', 'fsdfdssd', 'fsdafadsds']
如果没有itertools
,您可以使用以下食谱:
with open('a1.txt') as f,open('a1.txt') as g :
f.next()
it=f
for line in g :
n=next(f)
try :
if n.strip()=='-----END-----':
print line
except StopIteration:
break
结果:
fdsfdsfdasadsad
fsdfdssd
fsdafadsds
请注意,文件对象是一个迭代器,您可以在每次迭代中通过next
函数从中获取下一个项目。所以我们将文件中每一行的下一行与下一行(剥离)进行比较,如果它等于'-----END-----'
我们打印它。
答案 4 :(得分:0)
split
就好了,不需要其他工具。还要将结束标记及其后的所有内容分开:
with open("file.txt") as f:
blocks = [part.split('-----END-----')[0].strip()
for part in f.read().split('-----BEGIN-----')[1:]]