我的文字看起来像这样:
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
答案 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模块的MULTILINE
和DOTALL
标志。
#!/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
的第一个字符串一样。