Python线.分割两个界限之间

2024-04-26 14:44:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个包含以下数据的文本文件:

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-----”分隔符之间的数据提取到数组中。在

这就是我尝试过的:

^{pr2}$

但是,这显然会获取'----BEGIN-----'分隔符之后的所有数据。在

我怎样才能加上结束计时器?在

请注意,该文件相当大,大约为1GB。在


Tags: 数据namerawschematypecolumnlocalizedend
3条回答

如果您的文件足够小,可以将整个文件加载到内存中,那么使用正则表达式(又称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)

输出

^{pr2}$

这段代码创建了一个已编译的regex模式;在这种情况下,这并不是绝对必要的,因为我们只使用了一次模式,但它确实使代码看起来更整洁。在

该正则表达式查找由'beginstr''\n' + endstr分隔的子字符串。由于使用了分组括号,findall调用只捕获那些分隔符之间的内容。我在这些圆括号中放了一个'\n',这样捕获的子字符串总是有一个尾随的换行符。在

对于和之间的多行,您希望将数据分为多个部分,只需捕获每个以-----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)

这些部分将被分成子列表:

^{pr2}$

使用with打开文件,不要调用readlines,除非需要一个列表,否则可以像上面一样迭代file对象,而不必将所有内容存储在内存中。在

或使用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']

一个file对象返回它自己的迭代器,所以每次我们迭代或调用takewhile使用行时,takewhile将继续获取行,直到我们点击-----END----然后我们继续迭代,直到找到另一条-----BEGIN-----行,如果这些行总是以-开头,而没有其他行以if line[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']

如果您想要单个字符串调用联接:

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)

这将解决你的目的。在

相关问题 更多 >