Python line.split 两个分隔符之间
Python line.split between two delimeters
我有一个包含以下数据的文本文件:
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。
您可以使用 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-----'
我们打印它。
对于 和 之间的多行,您希望将数据分成多个部分,只需捕获以 -----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
打开你的文件,除非你想要一个列表,否则不要调用 readlines,你可以像上面那样遍历文件对象,而不用将所有内容存储在内存中。
或使用 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']
一个文件对象 returns 它自己的迭代器所以每次我们迭代或调用 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-----
试试这个:
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)
这将解决您的目的。
如果您的文件小到足以将整个文件加载到内存中,那么使用正则表达式(aka regex)可能是最好的方法。
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'
,这样捕获的子字符串将始终有一个尾随换行符。
split
单独使用就好,不需要其他工具。还要拆分结束标记及其后的所有内容:
with open("file.txt") as f:
blocks = [part.split('-----END-----')[0].strip()
for part in f.read().split('-----BEGIN-----')[1:]]
我有一个包含以下数据的文本文件:
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。
您可以使用 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-----'
我们打印它。
对于 和 之间的多行,您希望将数据分成多个部分,只需捕获以 -----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
打开你的文件,除非你想要一个列表,否则不要调用 readlines,你可以像上面那样遍历文件对象,而不用将所有内容存储在内存中。
或使用 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']
一个文件对象 returns 它自己的迭代器所以每次我们迭代或调用 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-----
试试这个:
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)
这将解决您的目的。
如果您的文件小到足以将整个文件加载到内存中,那么使用正则表达式(aka regex)可能是最好的方法。
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'
,这样捕获的子字符串将始终有一个尾随换行符。
split
单独使用就好,不需要其他工具。还要拆分结束标记及其后的所有内容:
with open("file.txt") as f:
blocks = [part.split('-----END-----')[0].strip()
for part in f.read().split('-----BEGIN-----')[1:]]