我有一堆文本文件,都是相同的格式(下面是一个片段,真实文件更长):
Molecular weight = 43057.32 Residues = 391
Average Residue Weight = 110.121 Charge = -10.0
Isoelectric Point = 4.8926
Residue Number Mole% DayhoffStat
A = Ala 24 6.138 0.714
B = Asx 0 0.000 0.000
C = Cys 9 2.302 0.794
Property Residues Number Mole%
Tiny (A+C+G+S+T) 135 34.527
Small (A+B+C+D+G+N+P+S+T+V) 222 56.777
Aliphatic (A+I+L+V) 97 24.808
我必须提取所有这些变量并处理它们。我打算编写一些代码,每次执行一行,并通过一系列拆分,剥离等函数提取相关信息。
这是人们用python做的一个非常常见的任务,所以我认为必须有一个更简单的方法。
是否有任何模块或方法允许以下内容:
template = """
Molecular weight = {0} Residues = {1}
Average Residue Weight = {2} Charge = {3}
Isoelectric Point = {4}
Residue Number Mole% DayhoffStat
A = Ala {4} {5} {6}
B = Asx {7} {8} {9}
C = Cys {10} {11} {12}
Property Residues Number Mole%
Tiny (A+C+G+S+T) {14} {15}
Small (A+B+C+D+G+N+P+S+T+V) {16} {17}
Aliphatic (A+I+L+V) {18} {19}"""
然后,要按照上述格式从另一个输入文件中提取变量,您将执行以下操作:
list_of_vars = Parse(template, infile)
请注意,虽然相同的变量将出现在同一行的每个文件中,但它们可以向右移动几个字符,具体取决于同一行上它前面的值有多大。
文件是emboss pepstats的输出,以防有人想知道。
感谢大家的快速回复。这里的解决方案是在re模块中使用findall函数。以下是一个简单的示例:
import re
class TemplateParser:
def __init__(self, template):
self.m_template = template.replace('{}', r'[\s]*([\d\-\.]+)[\s]*')
def ParseString(self, filename):
return re.findall(self.m_template, filename, re.DOTALL|re.MULTILINE)[0]
template = """
Molecular weight = {} Residues = {}
Average Residue Weight = {} Charge = {}
Isoelectric Point = {}
Residue Number Mole% DayhoffStat
A = Ala {} {} {}
B = Asx {} {} {}
C = Cys {} {} {}
Property Residues Number Mole%
Tiny \(A\+C\+G\+S\+T\) {} {}
Small \(A\+B\+C\+D\+G\+N\+P\+S\+T\+V\) {} {}
Aliphatic \(A\+I\+L\+V\) {} {}"""
ParseString函数成功返回一个字符串列表,然后我可以处理它。由于文件总是相同的格式,我能够成功处理我的所有文件。我只有两个问题。
1)正如你在上面所看到的那样,我已经在我的模板文件中逃脱了所有正则表达式字符,这并不是什么大不了的事。
2)正如我上面提到的,这个模板只是我需要解析的实际文件的一小部分。当我用我的真实数据尝试这个时,重新抛出以下错误:
"sorry, but this version only supports 100 named groups" AssertionError: sorry, but this version only supports 100 named groups
我通过将模板字符串分成3个部分来解决这个问题,使用3个不同的模板运行ParseString函数3次,并将列表结果一起添加。
再次感谢!
答案 0 :(得分:1)
这是一个艰难的开始
In [3]: data = """Molecular weight = 43057.32 Residues = 391
...: Average Residue Weight = 110.121 Charge = -10.0
...: Isoelectric Point = 4.8926
...:
...: Residue Number Mole% DayhoffStat
...: A = Ala 24 6.138 0.714
...: B = Asx 0 0.000 0.000
...: C = Cys 9 2.302 0.794
...:
...: Property Residues Number Mole%
...: Tiny (A+C+G+S+T) 135 34.527
...: Small (A+B+C+D+G+N+P+S+T+V) 222 56.777
...: Aliphatic (A+I+L+V) 97 24.808
...: """
In [5]: rx=r'Molecular weight += +([0-9\.]+).*Residues += +([0-9]+).*Average Residue Weight += +([0-9\.]+).*Charge += +([-+]*[0-9\.]+)'
rx=r'Molecular weight += +([0-9\.]+).*Residues += +([0-9]+).*Average Residue Weight += +([0-9\.]+).*Charge += +([-+]*[0-9\.]+)'
In [7]: import re
In [12]: re.findall(rx, data, re.DOTALL|re.MULTILINE)
Out[12]: [('43057.32', '391', '110.121', '-10.0')]
如您所见,这将从文件中提取前4个字段。如果您确实拥有这样的固定格式文件,则可以扩展正则表达式以在一次调用中获取所有数据。
你需要修改子表达式以获得正确的浮点格式等 - 正如我所说,这是一个快速的概念验证。如果真实文件明显更大,RE可能会变得非常冗长或难以调试。
仅供比较,以下是使用ctwheels在评论中提供的正则表达式获取相同数据的内容
In [13]: rx2='(?:\s*([a-zA-Z()+ ]+?)[ =]*)([-+]?\d+\.?\d*)'
In [14]: re.findall(rx2,data)
Out[14]:
[('Molecular weight', '43057.32'),
('Residues', '391'),
('Average Residue Weight', '110.121'),
('Charge', '-10.0'),
('Isoelectric Point', '4.8926'),
('Ala', '24'),
(' ', '6.138'),
(' ', '0.714'),
('Asx', '0'),
(' ', '0.000'),
(' ', '0.000'),
('Cys', '9'),
(' ', '2.302'),
(' ', '0.794'),
('Tiny (A+C+G+S+T)', '135'),
(' ', '34.527'),
('Small (A+B+C+D+G+N+P+S+T+V)', '222'),
(' ', '56.777'),
('Aliphatic (A+I+L+V)', '97'),
(' ', '24.808')]
In [15]: [m[1] for m in _]
Out[15]:
['43057.32',
'391',
'110.121',
'-10.0',
'4.8926',
'24',
'6.138',
'0.714',
'0',
'0.000',
'0.000',
'9',
'2.302',
'0.794',
'135',
'34.527',
'222',
'56.777',
'97',
'24.808']
哪个可能够好
答案 1 :(得分:1)
我可以看到此线程早已得到答复,但与OP具有相同的想法-使用模板解析文本数据-最终创建了模板文本解析器模块:https://ttp.readthedocs.io/en/latest/
示例python代码来解析OP的文本:
template = """
<group>
Molecular weight = {{ Molecular_weight }} Residues = {{ Residues }}
Average Residue Weight = {{ Average_Residue_Weight }} Charge = {{ Charge }}
Isoelectric Point = {{ Isoelectric_Point }}
<group name="table1">
## Residue Number Mole% DayhoffStat
{{ Residue | PHRASE }} {{ Number | DIGIT }} {{ Mole }} {{ DayhoffStat }}
</group>
<group name="table2">
## Property Residues Number Mole%
{{ Property }} {{ Residues }} {{ Number | DIGIT }} {{ Mole }}
</group>
</group>
"""
sample_data = """
Molecular weight = 43057.32 Residues = 391
Average Residue Weight = 110.121 Charge = -10.0
Isoelectric Point = 4.8926
Residue Number Mole% DayhoffStat
A = Ala 24 6.138 0.714
B = Asx 0 0.000 0.000
C = Cys 9 2.302 0.794
Property Residues Number Mole%
Tiny (A+C+G+S+T) 135 34.527
Small (A+B+C+D+G+N+P+S+T+V) 222 56.777
Aliphatic (A+I+L+V) 97 24.808
"""
from ttp import ttp
parser = ttp(sample_data, template)
result = parser.result(format="pprint")
print(result[0])
会产生:
[ { 'Average_Residue_Weight': '110.121',
'Charge': '-10.0',
'Isoelectric_Point': '4.8926',
'Molecular_weight': '43057.32',
'Residues': '391',
'table1': [ { 'DayhoffStat': '0.714',
'Mole': '6.138',
'Number': '24',
'Residue': 'A = Ala'},
{ 'DayhoffStat': '0.000',
'Mole': '0.000',
'Number': '0',
'Residue': 'B = Asx'},
{ 'DayhoffStat': '0.794',
'Mole': '2.302',
'Number': '9',
'Residue': 'C = Cys'}],
'table2': [ { 'Mole': '34.527',
'Number': '135',
'Property': 'Tiny',
'Residues': '(A+C+G+S+T)'},
{ 'Mole': '56.777',
'Number': '222',
'Property': 'Small',
'Residues': '(A+B+C+D+G+N+P+S+T+V)'},
{ 'Mole': '24.808',
'Number': '97',
'Property': 'Aliphatic',
'Residues': '(A+I+L+V)'}]}]