使用Python中的部分解析纯文本

时间:2014-12-12 07:15:51

标签: python parsing

我的文字看起来像这样:

    bla bla bla 
    bla some on wanted text....

****************************************************************************
List of 12 base pairs
      nt1              nt2             bp  name         Saenger     LW  DSSR
   1 Q.C0             Q.G22            C-G WC           19-XIX     cWW  cW-W
   2 Q.C1             Q.G21            C-G WC           19-XIX     cWW  cW-W
   3 Q.U2             Q.A20            U-A WC           20-XX      cWW  cW-W

****************************************************************************
another unwanted text ...
another unwanted text 

我想要的是提取以List of xxx base pairs开头的部分 并以它遇到的第一个*****结束。

有些情况下此部分根本没有出现。如果发生这种情况 它应该只输出"NONE"

我怎么能用Python做到这一点?

我尝试了这个,但失败了。它根本不打印任何输出。

import sys
import re

def main():
    """docstring for main"""
    infile = "myfile.txt"
    if len(sys.argv) > 1:
        infile = sys.argv[1]

    regex = re.compile(r"""List of (\d+) base pairs$""",re.VERBOSE)

    with open(infile, 'r') as tsvfile:
        tabreader = csv.reader(tsvfile, delimiter='\t')

        for row in tabreader:
            if row:
                line = row[0]
                match = regex.match(line)
                if match:
                    print line



if __name__ == '__main__':
    main()

在代码的最后,我希望它能打印出来:

      nt1              nt2             bp  name         Saenger     LW  DSSR
   1 Q.C0             Q.G22            C-G WC           19-XIX     cWW  cW-W
   2 Q.C1             Q.G21            C-G WC           19-XIX     cWW  cW-W
   3 Q.U2             Q.A20            U-A WC           20-XX      cWW  cW-W

或者只是

NONE

4 个答案:

答案 0 :(得分:3)

  

在代码的最后,我希望它能打印出来:

有几个问题。正则表达式有点过于严格。循环不识别正则表达式匹配作为起点。并且*******端点没有提前退出。

这里有一些工作代码可以帮助您入门:

import re

text = '''
    bla bla bla 
    bla some on wanted text....

****************************************************************************
List of 12 base pairs
      nt1              nt2             bp  name         Saenger     LW  DSSR
   1 Q.C0             Q.G22            C-G WC           19-XIX     cWW  cW-W
   2 Q.C1             Q.G21            C-G WC           19-XIX     cWW  cW-W
   3 Q.U2             Q.A20            U-A WC           20-XX      cWW  cW-W

****************************************************************************
another unwanted text ...
another unwanted text
'''

regex = re.compile(r"List of (\d+) base pairs")

started = False
for line in text.splitlines():
    if started:
        if line.startswith('*******'):
            break
        print line
    elif regex.search(line):
        started = True

答案 1 :(得分:2)

[ ]*List of \d+ base pairs\n*([\s\S]*?)(?=\n*\*{5,})

使用re.findall试用此正则表达式。请参阅演示。

https://regex101.com/r/eZ0yP4/20

import re
p = re.compile(r'[ ]*List of \d+ base pairs\n*([\s\S]*?)(?=\n*\*{5,})')
test_str = " bla bla bla \n bla some on wanted text....\n\n****************************************************************************\nList of 12 base pairs\n nt1 nt2 bp name Saenger LW DSSR\n 1 Q.C0 Q.G22 C-G WC 19-XIX cWW cW-W\n 2 Q.C1 Q.G21 C-G WC 19-XIX cWW cW-W\n 3 Q.U2 Q.A20 U-A WC 20-XX cWW cW-W\n\n****************************************************************************\nanother unwanted text ...\nanother unwanted text "

re.findall(p, test_str)

答案 2 :(得分:2)

您可以使用re模块的MULTILINEDOTALL标志。

#!/usr/bin/python

import re

f = open('myfile.txt','r').read()

pat = re.compile("""
    List\ of\ \d+\ base\ pairs$  # The start of the match
    (.*?)                        # Note ? to make it nongreedy
    ^[*]+$                       # The ending line
    """, re.MULTILINE+re.DOTALL+re.VERBOSE)

mat = pat.search(f)

if mat:
    print mat.group(1).strip()
else:
    print 'NONE'

注意:

  • 如果文件中有多行星标,则?.*需要Lists\ of\ ...才能使其无效。
  • 由于使用了re.VERBOSE,因此需要对初始字符串中的空格进行转义({{1}})。否则该空格将被忽略,并且不会找到匹配!

答案 3 :(得分:1)

可以尝试的另一个正则表达式:

f=open(my_file).read()
print ''.join(re.findall('\s+nt1[^\n]+\n|\s+\d+\sQ\.[^\n]+\n',f,re.M))

它接受以nt1 number + Q.开头的内容,就像传递给re.findall的第一个字符串一样。